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/oops/InstanceKlass.java
41161 views
1
/*
2
* Copyright (c) 2000, 2021, 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.oops;
26
27
import java.io.*;
28
import java.util.*;
29
import sun.jvm.hotspot.classfile.ClassLoaderData;
30
import sun.jvm.hotspot.debugger.*;
31
import sun.jvm.hotspot.memory.*;
32
import sun.jvm.hotspot.memory.Dictionary;
33
import sun.jvm.hotspot.runtime.*;
34
import sun.jvm.hotspot.types.*;
35
import sun.jvm.hotspot.utilities.*;
36
import sun.jvm.hotspot.utilities.Observable;
37
import sun.jvm.hotspot.utilities.Observer;
38
39
// An InstanceKlass is the VM level representation of a Java class.
40
41
public class InstanceKlass extends Klass {
42
static {
43
VM.registerVMInitializedObserver(new Observer() {
44
public void update(Observable o, Object data) {
45
initialize(VM.getVM().getTypeDataBase());
46
}
47
});
48
}
49
50
// field offset constants
51
private static int ACCESS_FLAGS_OFFSET;
52
private static int NAME_INDEX_OFFSET;
53
private static int SIGNATURE_INDEX_OFFSET;
54
private static int INITVAL_INDEX_OFFSET;
55
private static int LOW_OFFSET;
56
private static int HIGH_OFFSET;
57
private static int FIELD_SLOTS;
58
private static short FIELDINFO_TAG_SIZE;
59
private static short FIELDINFO_TAG_OFFSET;
60
61
// ClassState constants
62
private static int CLASS_STATE_ALLOCATED;
63
private static int CLASS_STATE_LOADED;
64
private static int CLASS_STATE_LINKED;
65
private static int CLASS_STATE_BEING_INITIALIZED;
66
private static int CLASS_STATE_FULLY_INITIALIZED;
67
private static int CLASS_STATE_INITIALIZATION_ERROR;
68
69
// _misc_flags constants
70
private static int MISC_REWRITTEN;
71
private static int MISC_HAS_NONSTATIC_FIELDS;
72
private static int MISC_SHOULD_VERIFY_CLASS;
73
private static int MISC_IS_CONTENDED;
74
private static int MISC_HAS_NONSTATIC_CONCRETE_METHODS;
75
private static int MISC_DECLARES_NONSTATIC_CONCRETE_METHODS;
76
private static int MISC_HAS_BEEN_REDEFINED;
77
private static int MISC_IS_SCRATCH_CLASS;
78
private static int MISC_IS_SHARED_BOOT_CLASS;
79
private static int MISC_IS_SHARED_PLATFORM_CLASS;
80
private static int MISC_IS_SHARED_APP_CLASS;
81
82
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
83
Type type = db.lookupType("InstanceKlass");
84
arrayKlasses = new MetadataField(type.getAddressField("_array_klasses"), 0);
85
methods = type.getAddressField("_methods");
86
defaultMethods = type.getAddressField("_default_methods");
87
methodOrdering = type.getAddressField("_method_ordering");
88
localInterfaces = type.getAddressField("_local_interfaces");
89
transitiveInterfaces = type.getAddressField("_transitive_interfaces");
90
fields = type.getAddressField("_fields");
91
javaFieldsCount = new CIntField(type.getCIntegerField("_java_fields_count"), 0);
92
constants = new MetadataField(type.getAddressField("_constants"), 0);
93
sourceDebugExtension = type.getAddressField("_source_debug_extension");
94
innerClasses = type.getAddressField("_inner_classes");
95
nonstaticFieldSize = new CIntField(type.getCIntegerField("_nonstatic_field_size"), 0);
96
staticFieldSize = new CIntField(type.getCIntegerField("_static_field_size"), 0);
97
staticOopFieldCount = new CIntField(type.getCIntegerField("_static_oop_field_count"), 0);
98
nonstaticOopMapSize = new CIntField(type.getCIntegerField("_nonstatic_oop_map_size"), 0);
99
isMarkedDependent = new CIntField(type.getCIntegerField("_is_marked_dependent"), 0);
100
initState = new CIntField(type.getCIntegerField("_init_state"), 0);
101
itableLen = new CIntField(type.getCIntegerField("_itable_len"), 0);
102
if (VM.getVM().isJvmtiSupported()) {
103
breakpoints = type.getAddressField("_breakpoints");
104
}
105
miscFlags = new CIntField(type.getCIntegerField("_misc_flags"), 0);
106
headerSize = type.getSize();
107
108
// read field offset constants
109
ACCESS_FLAGS_OFFSET = db.lookupIntConstant("FieldInfo::access_flags_offset").intValue();
110
NAME_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::name_index_offset").intValue();
111
SIGNATURE_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::signature_index_offset").intValue();
112
INITVAL_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::initval_index_offset").intValue();
113
LOW_OFFSET = db.lookupIntConstant("FieldInfo::low_packed_offset").intValue();
114
HIGH_OFFSET = db.lookupIntConstant("FieldInfo::high_packed_offset").intValue();
115
FIELD_SLOTS = db.lookupIntConstant("FieldInfo::field_slots").intValue();
116
FIELDINFO_TAG_SIZE = db.lookupIntConstant("FIELDINFO_TAG_SIZE").shortValue();
117
FIELDINFO_TAG_OFFSET = db.lookupIntConstant("FIELDINFO_TAG_OFFSET").shortValue();
118
119
// read ClassState constants
120
CLASS_STATE_ALLOCATED = db.lookupIntConstant("InstanceKlass::allocated").intValue();
121
CLASS_STATE_LOADED = db.lookupIntConstant("InstanceKlass::loaded").intValue();
122
CLASS_STATE_LINKED = db.lookupIntConstant("InstanceKlass::linked").intValue();
123
CLASS_STATE_BEING_INITIALIZED = db.lookupIntConstant("InstanceKlass::being_initialized").intValue();
124
CLASS_STATE_FULLY_INITIALIZED = db.lookupIntConstant("InstanceKlass::fully_initialized").intValue();
125
CLASS_STATE_INITIALIZATION_ERROR = db.lookupIntConstant("InstanceKlass::initialization_error").intValue();
126
127
MISC_REWRITTEN = db.lookupIntConstant("InstanceKlass::_misc_rewritten").intValue();
128
MISC_HAS_NONSTATIC_FIELDS = db.lookupIntConstant("InstanceKlass::_misc_has_nonstatic_fields").intValue();
129
MISC_SHOULD_VERIFY_CLASS = db.lookupIntConstant("InstanceKlass::_misc_should_verify_class").intValue();
130
MISC_IS_CONTENDED = db.lookupIntConstant("InstanceKlass::_misc_is_contended").intValue();
131
MISC_HAS_NONSTATIC_CONCRETE_METHODS = db.lookupIntConstant("InstanceKlass::_misc_has_nonstatic_concrete_methods").intValue();
132
MISC_DECLARES_NONSTATIC_CONCRETE_METHODS = db.lookupIntConstant("InstanceKlass::_misc_declares_nonstatic_concrete_methods").intValue();
133
MISC_HAS_BEEN_REDEFINED = db.lookupIntConstant("InstanceKlass::_misc_has_been_redefined").intValue();
134
MISC_IS_SCRATCH_CLASS = db.lookupIntConstant("InstanceKlass::_misc_is_scratch_class").intValue();
135
MISC_IS_SHARED_BOOT_CLASS = db.lookupIntConstant("InstanceKlass::_misc_is_shared_boot_class").intValue();
136
MISC_IS_SHARED_PLATFORM_CLASS = db.lookupIntConstant("InstanceKlass::_misc_is_shared_platform_class").intValue();
137
MISC_IS_SHARED_APP_CLASS = db.lookupIntConstant("InstanceKlass::_misc_is_shared_app_class").intValue();
138
}
139
140
public InstanceKlass(Address addr) {
141
super(addr);
142
143
// If the class hasn't yet reached the "loaded" init state, then don't go any further
144
// or we'll run into problems trying to look at fields that are not yet setup.
145
// Attempted lookups of this InstanceKlass via ClassLoaderDataGraph, ClassLoaderData,
146
// and Dictionary will all refuse to return it. The main purpose of allowing this
147
// InstanceKlass to initialize is so ClassLoaderData.getKlasses() will succeed, allowing
148
// ClassLoaderData.classesDo() to iterate over all Klasses (skipping those that are
149
// not yet fully loaded).
150
if (!isLoaded()) {
151
return;
152
}
153
154
if (getJavaFieldsCount() != getAllFieldsCount()) {
155
// Exercise the injected field logic
156
for (int i = getJavaFieldsCount(); i < getAllFieldsCount(); i++) {
157
getFieldName(i);
158
getFieldSignature(i);
159
}
160
}
161
}
162
163
private static MetadataField arrayKlasses;
164
private static AddressField methods;
165
private static AddressField defaultMethods;
166
private static AddressField methodOrdering;
167
private static AddressField localInterfaces;
168
private static AddressField transitiveInterfaces;
169
private static AddressField fields;
170
private static CIntField javaFieldsCount;
171
private static MetadataField constants;
172
private static AddressField sourceDebugExtension;
173
private static AddressField innerClasses;
174
private static CIntField nonstaticFieldSize;
175
private static CIntField staticFieldSize;
176
private static CIntField staticOopFieldCount;
177
private static CIntField nonstaticOopMapSize;
178
private static CIntField isMarkedDependent;
179
private static CIntField initState;
180
private static CIntField itableLen;
181
private static AddressField breakpoints;
182
private static CIntField miscFlags;
183
184
// type safe enum for ClassState from instanceKlass.hpp
185
public static class ClassState {
186
public static final ClassState ALLOCATED = new ClassState("allocated");
187
public static final ClassState LOADED = new ClassState("loaded");
188
public static final ClassState LINKED = new ClassState("linked");
189
public static final ClassState BEING_INITIALIZED = new ClassState("beingInitialized");
190
public static final ClassState FULLY_INITIALIZED = new ClassState("fullyInitialized");
191
public static final ClassState INITIALIZATION_ERROR = new ClassState("initializationError");
192
193
private ClassState(String value) {
194
this.value = value;
195
}
196
197
public String toString() {
198
return value;
199
}
200
201
private String value;
202
}
203
204
public int getInitStateAsInt() { return (int) initState.getValue(this); }
205
public ClassState getInitState() {
206
int state = getInitStateAsInt();
207
if (state == CLASS_STATE_ALLOCATED) {
208
return ClassState.ALLOCATED;
209
} else if (state == CLASS_STATE_LOADED) {
210
return ClassState.LOADED;
211
} else if (state == CLASS_STATE_LINKED) {
212
return ClassState.LINKED;
213
} else if (state == CLASS_STATE_BEING_INITIALIZED) {
214
return ClassState.BEING_INITIALIZED;
215
} else if (state == CLASS_STATE_FULLY_INITIALIZED) {
216
return ClassState.FULLY_INITIALIZED;
217
} else if (state == CLASS_STATE_INITIALIZATION_ERROR) {
218
return ClassState.INITIALIZATION_ERROR;
219
} else {
220
throw new RuntimeException("should not reach here");
221
}
222
}
223
224
// initialization state quaries
225
public boolean isLoaded() {
226
return getInitStateAsInt() >= CLASS_STATE_LOADED;
227
}
228
229
public boolean isLinked() {
230
return getInitStateAsInt() >= CLASS_STATE_LINKED;
231
}
232
233
public boolean isInitialized() {
234
return getInitStateAsInt() == CLASS_STATE_FULLY_INITIALIZED;
235
}
236
237
public boolean isNotInitialized() {
238
return getInitStateAsInt() < CLASS_STATE_BEING_INITIALIZED;
239
}
240
241
public boolean isBeingInitialized() {
242
return getInitStateAsInt() == CLASS_STATE_BEING_INITIALIZED;
243
}
244
245
public boolean isInErrorState() {
246
return getInitStateAsInt() == CLASS_STATE_INITIALIZATION_ERROR;
247
}
248
249
public int getClassStatus() {
250
int result = 0;
251
if (isLinked()) {
252
result |= JVMDIClassStatus.VERIFIED | JVMDIClassStatus.PREPARED;
253
}
254
255
if (isInitialized()) {
256
if (Assert.ASSERTS_ENABLED) {
257
Assert.that(isLinked(), "Class status is not consistent");
258
}
259
result |= JVMDIClassStatus.INITIALIZED;
260
}
261
262
if (isInErrorState()) {
263
result |= JVMDIClassStatus.ERROR;
264
}
265
return result;
266
}
267
268
// Byteside of the header
269
private static long headerSize;
270
271
public long getObjectSize(Oop object) {
272
return getSizeHelper() * VM.getVM().getAddressSize();
273
}
274
275
public long getSize() { // in number of bytes
276
long wordLength = VM.getVM().getBytesPerWord();
277
long size = getHeaderSize() +
278
(getVtableLen() +
279
getItableLen() +
280
getNonstaticOopMapSize()) * wordLength;
281
if (isInterface()) {
282
size += wordLength;
283
}
284
return alignSize(size);
285
}
286
287
private int getMiscFlags() {
288
return (int) miscFlags.getValue(this);
289
}
290
291
public static long getHeaderSize() { return headerSize; }
292
293
public short getFieldAccessFlags(int index) {
294
return getFields().at(index * FIELD_SLOTS + ACCESS_FLAGS_OFFSET);
295
}
296
297
public short getFieldNameIndex(int index) {
298
if (index >= getJavaFieldsCount()) throw new IndexOutOfBoundsException("not a Java field;");
299
return getFields().at(index * FIELD_SLOTS + NAME_INDEX_OFFSET);
300
}
301
302
public Symbol getFieldName(int index) {
303
int nameIndex = getFields().at(index * FIELD_SLOTS + NAME_INDEX_OFFSET);
304
if (index < getJavaFieldsCount()) {
305
return getConstants().getSymbolAt(nameIndex);
306
} else {
307
return vmSymbols.symbolAt(nameIndex);
308
}
309
}
310
311
public short getFieldSignatureIndex(int index) {
312
if (index >= getJavaFieldsCount()) throw new IndexOutOfBoundsException("not a Java field;");
313
return getFields().at(index * FIELD_SLOTS + SIGNATURE_INDEX_OFFSET);
314
}
315
316
public Symbol getFieldSignature(int index) {
317
int signatureIndex = getFields().at(index * FIELD_SLOTS + SIGNATURE_INDEX_OFFSET);
318
if (index < getJavaFieldsCount()) {
319
return getConstants().getSymbolAt(signatureIndex);
320
} else {
321
return vmSymbols.symbolAt(signatureIndex);
322
}
323
}
324
325
public short getFieldGenericSignatureIndex(int index) {
326
// int len = getFields().length();
327
int allFieldsCount = getAllFieldsCount();
328
int generic_signature_slot = allFieldsCount * FIELD_SLOTS;
329
for (int i = 0; i < allFieldsCount; i++) {
330
short flags = getFieldAccessFlags(i);
331
AccessFlags access = new AccessFlags(flags);
332
if (i == index) {
333
if (access.fieldHasGenericSignature()) {
334
return getFields().at(generic_signature_slot);
335
} else {
336
return 0;
337
}
338
} else {
339
if (access.fieldHasGenericSignature()) {
340
generic_signature_slot ++;
341
}
342
}
343
}
344
return 0;
345
}
346
347
public Symbol getFieldGenericSignature(int index) {
348
short genericSignatureIndex = getFieldGenericSignatureIndex(index);
349
if (genericSignatureIndex != 0) {
350
return getConstants().getSymbolAt(genericSignatureIndex);
351
}
352
return null;
353
}
354
355
public short getFieldInitialValueIndex(int index) {
356
if (index >= getJavaFieldsCount()) throw new IndexOutOfBoundsException("not a Java field;");
357
return getFields().at(index * FIELD_SLOTS + INITVAL_INDEX_OFFSET);
358
}
359
360
public int getFieldOffset(int index) {
361
U2Array fields = getFields();
362
short lo = fields.at(index * FIELD_SLOTS + LOW_OFFSET);
363
short hi = fields.at(index * FIELD_SLOTS + HIGH_OFFSET);
364
if ((lo & FIELDINFO_TAG_OFFSET) == FIELDINFO_TAG_OFFSET) {
365
return VM.getVM().buildIntFromShorts(lo, hi) >> FIELDINFO_TAG_SIZE;
366
}
367
throw new RuntimeException("should not reach here");
368
}
369
370
// Accessors for declared fields
371
public Klass getArrayKlasses() { return (Klass) arrayKlasses.getValue(this); }
372
public MethodArray getMethods() { return new MethodArray(methods.getValue(getAddress())); }
373
374
public MethodArray getDefaultMethods() {
375
if (defaultMethods != null) {
376
Address addr = defaultMethods.getValue(getAddress());
377
if ((addr != null) && (addr.getAddressAt(0) != null)) {
378
return new MethodArray(addr);
379
} else {
380
return null;
381
}
382
} else {
383
return null;
384
}
385
}
386
387
public KlassArray getLocalInterfaces() { return new KlassArray(localInterfaces.getValue(getAddress())); }
388
public KlassArray getTransitiveInterfaces() { return new KlassArray(transitiveInterfaces.getValue(getAddress())); }
389
public int getJavaFieldsCount() { return (int) javaFieldsCount.getValue(this); }
390
public int getAllFieldsCount() {
391
int len = getFields().length();
392
int allFieldsCount = 0;
393
for (; allFieldsCount*FIELD_SLOTS < len; allFieldsCount++) {
394
short flags = getFieldAccessFlags(allFieldsCount);
395
AccessFlags access = new AccessFlags(flags);
396
if (access.fieldHasGenericSignature()) {
397
len --;
398
}
399
}
400
return allFieldsCount;
401
}
402
public ConstantPool getConstants() { return (ConstantPool) constants.getValue(this); }
403
public Symbol getSourceFileName() { return getConstants().getSourceFileName(); }
404
public String getSourceDebugExtension(){ return CStringUtilities.getString(sourceDebugExtension.getValue(getAddress())); }
405
public long getNonstaticFieldSize() { return nonstaticFieldSize.getValue(this); }
406
public long getStaticOopFieldCount() { return staticOopFieldCount.getValue(this); }
407
public long getNonstaticOopMapSize() { return nonstaticOopMapSize.getValue(this); }
408
public boolean getIsMarkedDependent() { return isMarkedDependent.getValue(this) != 0; }
409
public long getItableLen() { return itableLen.getValue(this); }
410
public long majorVersion() { return getConstants().majorVersion(); }
411
public long minorVersion() { return getConstants().minorVersion(); }
412
public Symbol getGenericSignature() { return getConstants().getGenericSignature(); }
413
414
// "size helper" == instance size in words
415
public long getSizeHelper() {
416
int lh = getLayoutHelper();
417
if (Assert.ASSERTS_ENABLED) {
418
Assert.that(lh > 0, "layout helper initialized for instance class");
419
}
420
return lh / VM.getVM().getAddressSize();
421
}
422
423
// same as enum InnerClassAttributeOffset in VM code.
424
private static class InnerClassAttributeOffset {
425
// from JVM spec. "InnerClasses" attribute
426
public static int innerClassInnerClassInfoOffset;
427
public static int innerClassOuterClassInfoOffset;
428
public static int innerClassInnerNameOffset;
429
public static int innerClassAccessFlagsOffset;
430
public static int innerClassNextOffset;
431
static {
432
VM.registerVMInitializedObserver(new Observer() {
433
public void update(Observable o, Object data) {
434
initialize(VM.getVM().getTypeDataBase());
435
}
436
});
437
}
438
439
private static synchronized void initialize(TypeDataBase db) {
440
innerClassInnerClassInfoOffset = db.lookupIntConstant(
441
"InstanceKlass::inner_class_inner_class_info_offset").intValue();
442
innerClassOuterClassInfoOffset = db.lookupIntConstant(
443
"InstanceKlass::inner_class_outer_class_info_offset").intValue();
444
innerClassInnerNameOffset = db.lookupIntConstant(
445
"InstanceKlass::inner_class_inner_name_offset").intValue();
446
innerClassAccessFlagsOffset = db.lookupIntConstant(
447
"InstanceKlass::inner_class_access_flags_offset").intValue();
448
innerClassNextOffset = db.lookupIntConstant(
449
"InstanceKlass::inner_class_next_offset").intValue();
450
}
451
}
452
453
private static class EnclosingMethodAttributeOffset {
454
public static int enclosingMethodAttributeSize;
455
static {
456
VM.registerVMInitializedObserver(new Observer() {
457
public void update(Observable o, Object data) {
458
initialize(VM.getVM().getTypeDataBase());
459
}
460
});
461
}
462
private static synchronized void initialize(TypeDataBase db) {
463
enclosingMethodAttributeSize = db.lookupIntConstant("InstanceKlass::enclosing_method_attribute_size").intValue();
464
}
465
}
466
467
// refer to compute_modifier_flags in VM code.
468
public long computeModifierFlags() {
469
long access = getAccessFlags();
470
// But check if it happens to be member class.
471
U2Array innerClassList = getInnerClasses();
472
int length = (innerClassList == null)? 0 : (int) innerClassList.length();
473
if (length > 0) {
474
if (Assert.ASSERTS_ENABLED) {
475
Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0 ||
476
length % InnerClassAttributeOffset.innerClassNextOffset == EnclosingMethodAttributeOffset.enclosingMethodAttributeSize,
477
"just checking");
478
}
479
for (int i = 0; i < length; i += InnerClassAttributeOffset.innerClassNextOffset) {
480
if (i == length - EnclosingMethodAttributeOffset.enclosingMethodAttributeSize) {
481
break;
482
}
483
int ioff = innerClassList.at(i +
484
InnerClassAttributeOffset.innerClassInnerClassInfoOffset);
485
// 'ioff' can be zero.
486
// refer to JVM spec. section 4.7.5.
487
if (ioff != 0) {
488
// only look at classes that are already loaded
489
// since we are looking for the flags for our self.
490
Symbol name = getConstants().getKlassNameAt(ioff);
491
492
if (name.equals(getName())) {
493
// This is really a member class
494
access = innerClassList.at(i +
495
InnerClassAttributeOffset.innerClassAccessFlagsOffset);
496
break;
497
}
498
}
499
} // for inner classes
500
}
501
502
// Remember to strip ACC_SUPER bit
503
return (access & (~JVM_ACC_SUPER)) & JVM_ACC_WRITTEN_FLAGS;
504
}
505
506
507
// whether given Symbol is name of an inner/nested Klass of this Klass?
508
// anonymous and local classes are excluded.
509
public boolean isInnerClassName(Symbol sym) {
510
return isInInnerClasses(sym, false);
511
}
512
513
// whether given Symbol is name of an inner/nested Klass of this Klass?
514
// anonymous classes excluded, but local classes are included.
515
public boolean isInnerOrLocalClassName(Symbol sym) {
516
return isInInnerClasses(sym, true);
517
}
518
519
private boolean isInInnerClasses(Symbol sym, boolean includeLocals) {
520
U2Array innerClassList = getInnerClasses();
521
int length = ( innerClassList == null)? 0 : (int) innerClassList.length();
522
if (length > 0) {
523
if (Assert.ASSERTS_ENABLED) {
524
Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0 ||
525
length % InnerClassAttributeOffset.innerClassNextOffset == EnclosingMethodAttributeOffset.enclosingMethodAttributeSize,
526
"just checking");
527
}
528
for (int i = 0; i < length; i += InnerClassAttributeOffset.innerClassNextOffset) {
529
if (i == length - EnclosingMethodAttributeOffset.enclosingMethodAttributeSize) {
530
break;
531
}
532
int ioff = innerClassList.at(i +
533
InnerClassAttributeOffset.innerClassInnerClassInfoOffset);
534
// 'ioff' can be zero.
535
// refer to JVM spec. section 4.7.5.
536
if (ioff != 0) {
537
Symbol innerName = getConstants().getKlassNameAt(ioff);
538
Symbol myname = getName();
539
int ooff = innerClassList.at(i +
540
InnerClassAttributeOffset.innerClassOuterClassInfoOffset);
541
// for anonymous classes inner_name_index of InnerClasses
542
// attribute is zero.
543
int innerNameIndex = innerClassList.at(i +
544
InnerClassAttributeOffset.innerClassInnerNameOffset);
545
// if this is not a member (anonymous, local etc.), 'ooff' will be zero
546
// refer to JVM spec. section 4.7.5.
547
if (ooff == 0) {
548
if (includeLocals) {
549
// does it looks like my local class?
550
if (innerName.equals(sym) &&
551
innerName.asString().startsWith(myname.asString())) {
552
// exclude anonymous classes.
553
return (innerNameIndex != 0);
554
}
555
}
556
} else {
557
Symbol outerName = getConstants().getKlassNameAt(ooff);
558
559
// include only if current class is outer class.
560
if (outerName.equals(myname) && innerName.equals(sym)) {
561
return true;
562
}
563
}
564
}
565
} // for inner classes
566
return false;
567
} else {
568
return false;
569
}
570
}
571
572
public boolean implementsInterface(Klass k) {
573
if (Assert.ASSERTS_ENABLED) {
574
Assert.that(k.isInterface(), "should not reach here");
575
}
576
KlassArray interfaces = getTransitiveInterfaces();
577
final int len = interfaces.length();
578
for (int i = 0; i < len; i++) {
579
if (interfaces.getAt(i).equals(k)) return true;
580
}
581
return false;
582
}
583
584
boolean computeSubtypeOf(Klass k) {
585
if (k.isInterface()) {
586
return implementsInterface(k);
587
} else {
588
return super.computeSubtypeOf(k);
589
}
590
}
591
592
public void printValueOn(PrintStream tty) {
593
tty.print("InstanceKlass for " + getName().asString());
594
}
595
596
public void iterateFields(MetadataVisitor visitor) {
597
super.iterateFields(visitor);
598
visitor.doMetadata(arrayKlasses, true);
599
// visitor.doOop(methods, true);
600
// visitor.doOop(localInterfaces, true);
601
// visitor.doOop(transitiveInterfaces, true);
602
visitor.doCInt(nonstaticFieldSize, true);
603
visitor.doCInt(staticFieldSize, true);
604
visitor.doCInt(staticOopFieldCount, true);
605
visitor.doCInt(nonstaticOopMapSize, true);
606
visitor.doCInt(isMarkedDependent, true);
607
visitor.doCInt(initState, true);
608
visitor.doCInt(itableLen, true);
609
}
610
611
/*
612
* Visit the static fields of this InstanceKlass with the obj of
613
* the visitor set to the oop holding the fields, which is
614
* currently the java mirror.
615
*/
616
public void iterateStaticFields(OopVisitor visitor) {
617
visitor.setObj(getJavaMirror());
618
visitor.prologue();
619
iterateStaticFieldsInternal(visitor);
620
visitor.epilogue();
621
622
}
623
624
void iterateStaticFieldsInternal(OopVisitor visitor) {
625
int length = getJavaFieldsCount();
626
for (int index = 0; index < length; index++) {
627
short accessFlags = getFieldAccessFlags(index);
628
FieldType type = new FieldType(getFieldSignature(index));
629
AccessFlags access = new AccessFlags(accessFlags);
630
if (access.isStatic()) {
631
visitField(visitor, type, index);
632
}
633
}
634
}
635
636
public Klass getJavaSuper() {
637
return getSuper();
638
}
639
640
public static class StaticField {
641
public AccessFlags flags;
642
public Field field;
643
644
StaticField(Field field, AccessFlags flags) {
645
this.field = field;
646
this.flags = flags;
647
}
648
}
649
650
public Field[] getStaticFields() {
651
U2Array fields = getFields();
652
int length = getJavaFieldsCount();
653
ArrayList<Field> result = new ArrayList<>();
654
for (int index = 0; index < length; index++) {
655
Field f = newField(index);
656
if (f.isStatic()) {
657
result.add(f);
658
}
659
}
660
return result.toArray(new Field[result.size()]);
661
}
662
663
public void iterateNonStaticFields(OopVisitor visitor, Oop obj) {
664
if (getSuper() != null) {
665
((InstanceKlass) getSuper()).iterateNonStaticFields(visitor, obj);
666
}
667
int length = getJavaFieldsCount();
668
for (int index = 0; index < length; index++) {
669
short accessFlags = getFieldAccessFlags(index);
670
FieldType type = new FieldType(getFieldSignature(index));
671
AccessFlags access = new AccessFlags(accessFlags);
672
if (!access.isStatic()) {
673
visitField(visitor, type, index);
674
}
675
}
676
}
677
678
/** Field access by name. */
679
public Field findLocalField(String name, String sig) {
680
int length = getJavaFieldsCount();
681
for (int i = 0; i < length; i++) {
682
Symbol f_name = getFieldName(i);
683
Symbol f_sig = getFieldSignature(i);
684
if (f_name.equals(name) && f_sig.equals(sig)) {
685
return newField(i);
686
}
687
}
688
689
return null;
690
}
691
692
/** Find field in direct superinterfaces. */
693
public Field findInterfaceField(String name, String sig) {
694
KlassArray interfaces = getLocalInterfaces();
695
int n = interfaces.length();
696
for (int i = 0; i < n; i++) {
697
InstanceKlass intf1 = (InstanceKlass) interfaces.getAt(i);
698
if (Assert.ASSERTS_ENABLED) {
699
Assert.that(intf1.isInterface(), "just checking type");
700
}
701
// search for field in current interface
702
Field f = intf1.findLocalField(name, sig);
703
if (f != null) {
704
if (Assert.ASSERTS_ENABLED) {
705
Assert.that(f.getAccessFlagsObj().isStatic(), "interface field must be static");
706
}
707
return f;
708
}
709
// search for field in direct superinterfaces
710
f = intf1.findInterfaceField(name, sig);
711
if (f != null) return f;
712
}
713
// otherwise field lookup fails
714
return null;
715
}
716
717
/** Find field according to JVM spec 5.4.3.2, returns the klass in
718
which the field is defined. */
719
public Field findField(String name, String sig) {
720
// search order according to newest JVM spec (5.4.3.2, p.167).
721
// 1) search for field in current klass
722
Field f = findLocalField(name, sig);
723
if (f != null) return f;
724
725
// 2) search for field recursively in direct superinterfaces
726
f = findInterfaceField(name, sig);
727
if (f != null) return f;
728
729
// 3) apply field lookup recursively if superclass exists
730
InstanceKlass supr = (InstanceKlass) getSuper();
731
if (supr != null) return supr.findField(name, sig);
732
733
// 4) otherwise field lookup fails
734
return null;
735
}
736
737
/** Find field according to JVM spec 5.4.3.2, returns the klass in
738
which the field is defined (retained only for backward
739
compatibility with jdbx) */
740
public Field findFieldDbg(String name, String sig) {
741
return findField(name, sig);
742
}
743
744
/** Get field by its index in the fields array. Only designed for
745
use in a debugging system. */
746
public Field getFieldByIndex(int fieldIndex) {
747
return newField(fieldIndex);
748
}
749
750
751
/** Return a List of SA Fields for the fields declared in this class.
752
Inherited fields are not included.
753
Return an empty list if there are no fields declared in this class.
754
Only designed for use in a debugging system. */
755
public List<Field> getImmediateFields() {
756
// A list of Fields for each field declared in this class/interface,
757
// not including inherited fields.
758
int length = getJavaFieldsCount();
759
List<Field> immediateFields = new ArrayList<>(length);
760
for (int index = 0; index < length; index++) {
761
immediateFields.add(getFieldByIndex(index));
762
}
763
764
return immediateFields;
765
}
766
767
/** Return a List of SA Fields for all the java fields in this class,
768
including all inherited fields. This includes hidden
769
fields. Thus the returned list can contain fields with
770
the same name.
771
Return an empty list if there are no fields.
772
Only designed for use in a debugging system. */
773
public List<Field> getAllFields() {
774
// Contains a Field for each field in this class, including immediate
775
// fields and inherited fields.
776
List<Field> allFields = getImmediateFields();
777
778
// transitiveInterfaces contains all interfaces implemented
779
// by this class and its superclass chain with no duplicates.
780
781
KlassArray interfaces = getTransitiveInterfaces();
782
int n = interfaces.length();
783
for (int i = 0; i < n; i++) {
784
InstanceKlass intf1 = (InstanceKlass) interfaces.getAt(i);
785
if (Assert.ASSERTS_ENABLED) {
786
Assert.that(intf1.isInterface(), "just checking type");
787
}
788
allFields.addAll(intf1.getImmediateFields());
789
}
790
791
// Get all fields in the superclass, recursively. But, don't
792
// include fields in interfaces implemented by superclasses;
793
// we already have all those.
794
if (!isInterface()) {
795
InstanceKlass supr;
796
if ( (supr = (InstanceKlass) getSuper()) != null) {
797
allFields.addAll(supr.getImmediateFields());
798
}
799
}
800
801
return allFields;
802
}
803
804
805
/** Return a List of SA Methods declared directly in this class/interface.
806
Return an empty list if there are none, or if this isn't a class/
807
interface.
808
*/
809
public List<Method> getImmediateMethods() {
810
// Contains a Method for each method declared in this class/interface
811
// not including inherited methods.
812
813
MethodArray methods = getMethods();
814
int length = methods.length();
815
Method[] tmp = new Method[length];
816
817
IntArray methodOrdering = getMethodOrdering();
818
if (methodOrdering.length() != length) {
819
// no ordering info present
820
for (int index = 0; index < length; index++) {
821
tmp[index] = methods.at(index);
822
}
823
} else {
824
for (int index = 0; index < length; index++) {
825
int originalIndex = methodOrdering.at(index);
826
tmp[originalIndex] = methods.at(index);
827
}
828
}
829
830
return Arrays.asList(tmp);
831
}
832
833
/** Return a List containing an SA InstanceKlass for each
834
interface named in this class's 'implements' clause.
835
*/
836
public List<Klass> getDirectImplementedInterfaces() {
837
// Contains an InstanceKlass for each interface in this classes
838
// 'implements' clause.
839
840
KlassArray interfaces = getLocalInterfaces();
841
int length = interfaces.length();
842
List<Klass> directImplementedInterfaces = new ArrayList<>(length);
843
844
for (int index = 0; index < length; index ++) {
845
directImplementedInterfaces.add(interfaces.getAt(index));
846
}
847
848
return directImplementedInterfaces;
849
}
850
851
public Klass arrayKlassImpl(boolean orNull, int n) {
852
// FIXME: in reflective system this would need to change to
853
// actually allocate
854
if (getArrayKlasses() == null) { return null; }
855
ObjArrayKlass oak = (ObjArrayKlass) getArrayKlasses();
856
if (orNull) {
857
return oak.arrayKlassOrNull(n);
858
}
859
return oak.arrayKlass(n);
860
}
861
862
public Klass arrayKlassImpl(boolean orNull) {
863
return arrayKlassImpl(orNull, 1);
864
}
865
866
public String signature() {
867
return "L" + super.signature() + ";";
868
}
869
870
/** Find method in vtable. */
871
public Method findMethod(String name, String sig) {
872
return findMethod(getMethods(), name, sig);
873
}
874
875
/** Breakpoint support (see methods on Method* for details) */
876
public BreakpointInfo getBreakpoints() {
877
if (!VM.getVM().isJvmtiSupported()) {
878
return null;
879
}
880
Address addr = getAddress().getAddressAt(breakpoints.getOffset());
881
return (BreakpointInfo) VMObjectFactory.newObject(BreakpointInfo.class, addr);
882
}
883
884
public IntArray getMethodOrdering() {
885
Address addr = getAddress().getAddressAt(methodOrdering.getOffset());
886
return (IntArray) VMObjectFactory.newObject(IntArray.class, addr);
887
}
888
889
public U2Array getFields() {
890
Address addr = getAddress().getAddressAt(fields.getOffset());
891
return (U2Array) VMObjectFactory.newObject(U2Array.class, addr);
892
}
893
894
public U2Array getInnerClasses() {
895
Address addr = getAddress().getAddressAt(innerClasses.getOffset());
896
return (U2Array) VMObjectFactory.newObject(U2Array.class, addr);
897
}
898
899
900
//----------------------------------------------------------------------
901
// Internals only below this point
902
//
903
904
private void visitField(OopVisitor visitor, FieldType type, int index) {
905
Field f = newField(index);
906
if (type.isOop()) {
907
visitor.doOop((OopField) f, false);
908
return;
909
}
910
if (type.isByte()) {
911
visitor.doByte((ByteField) f, false);
912
return;
913
}
914
if (type.isChar()) {
915
visitor.doChar((CharField) f, false);
916
return;
917
}
918
if (type.isDouble()) {
919
visitor.doDouble((DoubleField) f, false);
920
return;
921
}
922
if (type.isFloat()) {
923
visitor.doFloat((FloatField) f, false);
924
return;
925
}
926
if (type.isInt()) {
927
visitor.doInt((IntField) f, false);
928
return;
929
}
930
if (type.isLong()) {
931
visitor.doLong((LongField) f, false);
932
return;
933
}
934
if (type.isShort()) {
935
visitor.doShort((ShortField) f, false);
936
return;
937
}
938
if (type.isBoolean()) {
939
visitor.doBoolean((BooleanField) f, false);
940
return;
941
}
942
}
943
944
// Creates new field from index in fields TypeArray
945
private Field newField(int index) {
946
FieldType type = new FieldType(getFieldSignature(index));
947
if (type.isOop()) {
948
if (VM.getVM().isCompressedOopsEnabled()) {
949
return new NarrowOopField(this, index);
950
} else {
951
return new OopField(this, index);
952
}
953
}
954
if (type.isByte()) {
955
return new ByteField(this, index);
956
}
957
if (type.isChar()) {
958
return new CharField(this, index);
959
}
960
if (type.isDouble()) {
961
return new DoubleField(this, index);
962
}
963
if (type.isFloat()) {
964
return new FloatField(this, index);
965
}
966
if (type.isInt()) {
967
return new IntField(this, index);
968
}
969
if (type.isLong()) {
970
return new LongField(this, index);
971
}
972
if (type.isShort()) {
973
return new ShortField(this, index);
974
}
975
if (type.isBoolean()) {
976
return new BooleanField(this, index);
977
}
978
throw new RuntimeException("Illegal field type at index " + index);
979
}
980
981
private static Method findMethod(MethodArray methods, String name, String signature) {
982
int index = linearSearch(methods, name, signature);
983
if (index != -1) {
984
return methods.at(index);
985
} else {
986
return null;
987
}
988
}
989
990
private static int linearSearch(MethodArray methods, String name, String signature) {
991
int len = (int) methods.length();
992
for (int index = 0; index < len; index++) {
993
Method m = methods.at(index);
994
if (m.getSignature().equals(signature) && m.getName().equals(name)) {
995
return index;
996
}
997
}
998
return -1;
999
}
1000
1001
public void dumpReplayData(PrintStream out) {
1002
ConstantPool cp = getConstants();
1003
1004
// Try to record related loaded classes
1005
Klass sub = getSubklassKlass();
1006
while (sub != null) {
1007
if (sub instanceof InstanceKlass) {
1008
out.println("instanceKlass " + sub.getName().asString());
1009
}
1010
sub = sub.getNextSiblingKlass();
1011
}
1012
1013
final int length = (int) cp.getLength();
1014
out.print("ciInstanceKlass " + getName().asString() + " " + (isLinked() ? 1 : 0) + " " + (isInitialized() ? 1 : 0) + " " + length);
1015
for (int index = 1; index < length; index++) {
1016
out.print(" " + cp.getTags().at(index));
1017
}
1018
out.println();
1019
if (isInitialized()) {
1020
Field[] staticFields = getStaticFields();
1021
for (int i = 0; i < staticFields.length; i++) {
1022
Field f = staticFields[i];
1023
Oop mirror = getJavaMirror();
1024
if (f.isFinal() && !f.hasInitialValue()) {
1025
out.print("staticfield " + getName().asString() + " " +
1026
OopUtilities.escapeString(f.getID().getName()) + " " +
1027
f.getFieldType().getSignature().asString() + " ");
1028
if (f instanceof ByteField) {
1029
ByteField bf = (ByteField)f;
1030
out.println(bf.getValue(mirror));
1031
} else if (f instanceof BooleanField) {
1032
BooleanField bf = (BooleanField)f;
1033
out.println(bf.getValue(mirror) ? 1 : 0);
1034
} else if (f instanceof ShortField) {
1035
ShortField bf = (ShortField)f;
1036
out.println(bf.getValue(mirror));
1037
} else if (f instanceof CharField) {
1038
CharField bf = (CharField)f;
1039
out.println(bf.getValue(mirror) & 0xffff);
1040
} else if (f instanceof IntField) {
1041
IntField bf = (IntField)f;
1042
out.println(bf.getValue(mirror));
1043
} else if (f instanceof LongField) {
1044
LongField bf = (LongField)f;
1045
out.println(bf.getValue(mirror));
1046
} else if (f instanceof FloatField) {
1047
FloatField bf = (FloatField)f;
1048
out.println(Float.floatToRawIntBits(bf.getValue(mirror)));
1049
} else if (f instanceof DoubleField) {
1050
DoubleField bf = (DoubleField)f;
1051
out.println(Double.doubleToRawLongBits(bf.getValue(mirror)));
1052
} else if (f instanceof OopField) {
1053
OopField bf = (OopField)f;
1054
1055
Oop value = bf.getValue(mirror);
1056
if (value == null) {
1057
out.println("null");
1058
} else if (value.isInstance()) {
1059
Instance inst = (Instance)value;
1060
if (inst.isA(SystemDictionary.getStringKlass())) {
1061
out.println("\"" + OopUtilities.stringOopToEscapedString(inst) + "\"");
1062
} else {
1063
out.println(inst.getKlass().getName().asString());
1064
}
1065
} else if (value.isObjArray()) {
1066
ObjArray oa = (ObjArray)value;
1067
Klass ek = (ObjArrayKlass)oa.getKlass();
1068
out.println(oa.getLength() + " " + ek.getName().asString());
1069
} else if (value.isTypeArray()) {
1070
TypeArray ta = (TypeArray)value;
1071
out.println(ta.getLength());
1072
} else {
1073
out.println(value);
1074
}
1075
}
1076
}
1077
}
1078
}
1079
}
1080
}
1081
1082