Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/ClassLoaderStats.java
41161 views
1
/*
2
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*
23
*/
24
25
package sun.jvm.hotspot.tools;
26
27
import java.io.*;
28
import java.util.*;
29
30
import sun.jvm.hotspot.debugger.*;
31
import sun.jvm.hotspot.classfile.*;
32
import sun.jvm.hotspot.memory.*;
33
import sun.jvm.hotspot.oops.*;
34
import sun.jvm.hotspot.runtime.*;
35
import sun.jvm.hotspot.utilities.*;
36
37
/**
38
A command line tool to print class loader statistics.
39
*/
40
41
public class ClassLoaderStats extends Tool {
42
boolean verbose = true;
43
44
public ClassLoaderStats() {
45
super();
46
}
47
48
public ClassLoaderStats(JVMDebugger d) {
49
super(d);
50
}
51
52
@Override
53
public String getName() {
54
return "classLoaderStats";
55
}
56
57
public static void main(String[] args) {
58
ClassLoaderStats cls = new ClassLoaderStats();
59
cls.execute(args);
60
}
61
62
private static class ClassData {
63
Klass klass;
64
long size;
65
66
ClassData(Klass klass, long size) {
67
this.klass = klass; this.size = size;
68
}
69
}
70
71
private static class LoaderData {
72
long numClasses;
73
long classSize;
74
List<ClassData> classDetail = new ArrayList<>();
75
}
76
77
public void run() {
78
printClassLoaderStatistics();
79
}
80
81
private void printClassLoaderStatistics() {
82
final PrintStream out = System.out;
83
final PrintStream err = System.err;
84
final Map<Oop, LoaderData> loaderMap = new HashMap<>();
85
// loader data for bootstrap class loader
86
final LoaderData bootstrapLoaderData = new LoaderData();
87
if (verbose) {
88
err.print("finding class loader instances ..");
89
}
90
91
VM vm = VM.getVM();
92
ObjectHeap heap = vm.getObjectHeap();
93
Klass classLoaderKlass = vm.getSystemDictionary().getClassLoaderKlass();
94
try {
95
heap.iterateObjectsOfKlass(new DefaultHeapVisitor() {
96
public boolean doObj(Oop oop) {
97
loaderMap.put(oop, new LoaderData());
98
return false;
99
}
100
}, classLoaderKlass);
101
} catch (Exception se) {
102
se.printStackTrace();
103
}
104
105
if (verbose) {
106
err.println("done.");
107
err.print("computing per loader stat ..");
108
}
109
110
ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();
111
cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
112
public void visit(Klass k) {
113
if (! (k instanceof InstanceKlass)) {
114
return;
115
}
116
Oop loader = ((InstanceKlass) k).getClassLoader();
117
LoaderData ld = (loader != null) ? (LoaderData)loaderMap.get(loader)
118
: bootstrapLoaderData;
119
if (ld != null) {
120
ld.numClasses++;
121
long size = computeSize((InstanceKlass)k);
122
ld.classDetail.add(new ClassData(k, size));
123
ld.classSize += size;
124
}
125
}
126
});
127
128
if (verbose) {
129
err.println("done.");
130
err.print("please wait.. computing liveness");
131
}
132
133
// compute reverse pointer analysis (takes long time for larger app)
134
ReversePtrsAnalysis analysis = new ReversePtrsAnalysis();
135
136
if (verbose) {
137
analysis.setHeapProgressThunk(new HeapProgressThunk() {
138
public void heapIterationFractionUpdate(double fractionOfHeapVisited) {
139
err.print('.');
140
}
141
// This will be called after the iteration is complete
142
public void heapIterationComplete() {
143
err.println("done.");
144
}
145
});
146
}
147
148
try {
149
analysis.run();
150
} catch (Exception e) {
151
// e.printStackTrace();
152
if (verbose)
153
err.println("liveness analysis may be inaccurate ...");
154
}
155
ReversePtrs liveness = VM.getVM().getRevPtrs();
156
157
out.println("class_loader\tclasses\tbytes\tparent_loader\talive?\ttype");
158
out.println();
159
160
long numClassLoaders = 1L;
161
long totalNumClasses = bootstrapLoaderData.numClasses;
162
long totalClassSize = bootstrapLoaderData.classSize;
163
long numAliveLoaders = 1L;
164
long numDeadLoaders = 0L;
165
166
// print bootstrap loader details
167
out.print("<bootstrap>");
168
out.print('\t');
169
out.print(bootstrapLoaderData.numClasses);
170
out.print('\t');
171
out.print(bootstrapLoaderData.classSize);
172
out.print('\t');
173
out.print(" null ");
174
out.print('\t');
175
// bootstrap loader is always alive
176
out.print("live");
177
out.print('\t');
178
out.println("<internal>");
179
180
for (Iterator keyItr = loaderMap.keySet().iterator(); keyItr.hasNext();) {
181
Oop loader = (Oop) keyItr.next();
182
LoaderData data = (LoaderData) loaderMap.get(loader);
183
numClassLoaders ++;
184
totalNumClasses += data.numClasses;
185
totalClassSize += data.classSize;
186
187
out.print(loader.getHandle());
188
out.print('\t');
189
out.print(data.numClasses);
190
out.print('\t');
191
out.print(data.classSize);
192
out.print('\t');
193
194
class ParentFinder extends DefaultOopVisitor {
195
public void doOop(OopField field, boolean isVMField) {
196
if (field.getID().getName().equals("parent")) {
197
parent = field.getValue(getObj());
198
}
199
}
200
private Oop parent = null;
201
public Oop getParent() { return parent; }
202
}
203
204
ParentFinder parentFinder = new ParentFinder();
205
loader.iterate(parentFinder, false);
206
Oop parent = parentFinder.getParent();
207
out.print((parent != null)? parent.getHandle().toString() : " null ");
208
out.print('\t');
209
boolean alive = (liveness != null) ? (liveness.get(loader) != null) : true;
210
out.print(alive? "live" : "dead");
211
if (alive) numAliveLoaders++; else numDeadLoaders++;
212
out.print('\t');
213
Klass loaderKlass = loader.getKlass();
214
if (loaderKlass != null) {
215
out.print(loaderKlass.getName().asString());
216
out.print('@');
217
out.print(loader.getKlass().getAddress());
218
} else {
219
out.print(" null! ");
220
}
221
out.println();
222
}
223
224
out.println();
225
// summary line
226
out.print("total = ");
227
out.print(numClassLoaders);
228
out.print('\t');
229
out.print(totalNumClasses);
230
out.print('\t');
231
out.print(totalClassSize);
232
out.print('\t');
233
out.print(" N/A ");
234
out.print('\t');
235
out.print("alive=");
236
out.print(numAliveLoaders);
237
out.print(", dead=");
238
out.print(numDeadLoaders);
239
out.print('\t');
240
out.print(" N/A ");
241
out.println();
242
}
243
244
private static long objectSize(Oop oop) {
245
return oop == null ? 0L : oop.getObjectSize();
246
}
247
248
// Don't count the shared empty arrays
249
private static long arraySize(GenericArray arr) {
250
return arr.getLength() != 0L ? arr.getSize() : 0L;
251
}
252
253
private long computeSize(InstanceKlass k) {
254
long size = 0L;
255
// the InstanceKlass object itself
256
size += k.getSize();
257
258
// Constant pool
259
ConstantPool cp = k.getConstants();
260
size += cp.getSize();
261
if (cp.getCache() != null) {
262
size += cp.getCache().getSize();
263
}
264
size += arraySize(cp.getTags());
265
266
// Interfaces
267
size += arraySize(k.getLocalInterfaces());
268
size += arraySize(k.getTransitiveInterfaces());
269
270
// Inner classes
271
size += arraySize(k.getInnerClasses());
272
273
// Fields
274
size += arraySize(k.getFields());
275
276
// Methods
277
MethodArray methods = k.getMethods();
278
int nmethods = (int) methods.getLength();
279
if (nmethods != 0L) {
280
size += methods.getSize();
281
for (int i = 0; i < nmethods; ++i) {
282
Method m = methods.at(i);
283
size += m.getSize();
284
size += m.getConstMethod().getSize();
285
}
286
}
287
288
return size;
289
}
290
}
291
292