Skip to content

Commit 41447f4

Browse files
committed
[GR-65630] Include loaded array classes in JDWP commands.
PullRequest: graal/21105
2 parents 67ce159 + a8e66a0 commit 41447f4

File tree

17 files changed

+165
-78
lines changed

17 files changed

+165
-78
lines changed

espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/JDWPContext.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
import java.nio.file.Path;
2626
import java.util.List;
27+
import java.util.Set;
2728

2829
import com.oracle.truffle.api.TruffleLanguage;
2930
import com.oracle.truffle.api.frame.Frame;
@@ -65,7 +66,7 @@ public interface JDWPContext {
6566
*
6667
* @return array containing every class loaded
6768
*/
68-
KlassRef[] getAllLoadedClasses();
69+
Set<? extends KlassRef> getAllLoadedClasses();
6970

7071
/**
7172
* Finds the method for which an root node was created from.
@@ -177,9 +178,9 @@ public interface JDWPContext {
177178
* Returns all classes for which the class loader initiated loading.
178179
*
179180
* @param classLoader guest language class loader
180-
* @return array of classes initiated by the class loader
181+
* @return set of classes initiated by the class loader
181182
*/
182-
List<? extends KlassRef> getInitiatedClasses(Object classLoader);
183+
Set<? extends KlassRef> getInitiatedClasses(Object classLoader);
183184

184185
/**
185186
* Retrieves the field value of a static field.

espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/KlassRef.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,12 +147,13 @@ public interface KlassRef {
147147
int getModifiers();
148148

149149
/**
150-
* Returns the array klass for this klass with the given dimensions.
150+
* Returns the array klass for this klass with the given dimensions iff the array type was
151+
* loaded.
151152
*
152153
* @param dimensions array dimension
153154
* @return array klass
154155
*/
155-
KlassRef getArrayClass(int dimensions);
156+
KlassRef getArrayClassNoCreate(int dimensions);
156157

157158
/**
158159
* Returns the major version of the corresponding class file for this klass.

espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import java.util.ArrayList;
2828
import java.util.Collections;
2929
import java.util.List;
30+
import java.util.Set;
3031

3132
import com.oracle.truffle.api.interop.InteropException;
3233
import com.oracle.truffle.espresso.classfile.attributes.LineNumberTableRef;
@@ -112,16 +113,16 @@ static class ALL_CLASSES {
112113
static CommandResult createReply(Packet packet, JDWPContext context, DebuggerController controller) {
113114
PacketStream reply = new PacketStream().replyPacket().id(packet.id);
114115

115-
KlassRef[] allLoadedClasses = context.getAllLoadedClasses();
116-
reply.writeInt(allLoadedClasses.length);
116+
Set<? extends KlassRef> allLoadedClasses = context.getAllLoadedClasses();
117+
reply.writeInt(allLoadedClasses.size());
117118

118119
for (KlassRef klass : allLoadedClasses) {
119120
reply.writeByte(TypeTag.getKind(klass));
120121
reply.writeLong(context.getIds().getIdAsLong(klass));
121122
reply.writeString(klass.getTypeAsString());
122123
reply.writeInt(klass.getStatus());
123124
}
124-
controller.fine(() -> "Loaded classes: " + allLoadedClasses.length);
125+
controller.fine(() -> "Loaded classes: " + allLoadedClasses.size());
125126

126127
return new CommandResult(reply);
127128
}
@@ -438,8 +439,8 @@ static class ALL_CLASSES_WITH_GENERIC {
438439
static CommandResult createReply(Packet packet, JDWPContext context) {
439440
PacketStream reply = new PacketStream().replyPacket().id(packet.id);
440441

441-
KlassRef[] allLoadedClasses = context.getAllLoadedClasses();
442-
reply.writeInt(allLoadedClasses.length);
442+
Set<? extends KlassRef> allLoadedClasses = context.getAllLoadedClasses();
443+
reply.writeInt(allLoadedClasses.size());
443444

444445
for (KlassRef klass : allLoadedClasses) {
445446
reply.writeByte(TypeTag.getKind(klass));
@@ -2659,7 +2660,7 @@ static CommandResult createReply(Packet packet, JDWPContext context) {
26592660
if (classLoader == null) {
26602661
return new CommandResult(reply);
26612662
}
2662-
List<? extends KlassRef> klasses = context.getInitiatedClasses(classLoader);
2663+
Set<? extends KlassRef> klasses = context.getInitiatedClasses(classLoader);
26632664

26642665
reply.writeInt(klasses.size());
26652666

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/cds/Reader.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,7 @@ private void skipGuestClass() {
464464
Symbol<Type> elementalTypeSymbol = espressoContext.getTypes().getElementalType(typeSymbol);
465465
if (TypeSymbols.isArray(typeSymbol) && TypeSymbols.isPrimitive(elementalTypeSymbol)) {
466466
Klass elemental = meta.resolvePrimitive(elementalTypeSymbol);
467-
klass = elemental.getArrayClass(TypeSymbols.getArrayDimensions(typeSymbol));
467+
klass = elemental.getArrayKlass(TypeSymbols.getArrayDimensions(typeSymbol));
468468
} else {
469469
klass = meta.loadKlassOrNull(typeSymbol, StaticObject.NULL, StaticObject.NULL);
470470
}

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ClassRegistries.java

Lines changed: 54 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@
2525
import static com.oracle.truffle.espresso.impl.LoadingConstraints.INVALID_LOADER_ID;
2626

2727
import java.util.ArrayList;
28+
import java.util.Arrays;
29+
import java.util.Collection;
2830
import java.util.Collections;
31+
import java.util.HashSet;
2932
import java.util.List;
3033
import java.util.Set;
3134
import java.util.WeakHashMap;
@@ -190,7 +193,7 @@ public Klass findLoadedClass(Symbol<Type> type, @JavaType(ClassLoader.class) Sta
190193
if (elemental == null) {
191194
return null;
192195
}
193-
return elemental.getArrayClass(TypeSymbols.getArrayDimensions(type));
196+
return elemental.getArrayKlass(TypeSymbols.getArrayDimensions(type));
194197
}
195198

196199
ClassRegistry registry = getClassRegistry(classLoader);
@@ -199,16 +202,44 @@ public Klass findLoadedClass(Symbol<Type> type, @JavaType(ClassLoader.class) Sta
199202
}
200203

201204
@TruffleBoundary
202-
public List<Klass> getLoadedClassesByLoader(StaticObject classLoader) {
205+
public Set<Klass> getLoadedClassesByLoader(StaticObject classLoader, boolean includeHidden) {
203206
if (classLoader == StaticObject.NULL) {
204-
ArrayList<Klass> result = new ArrayList<>(bootClassRegistry.classes.size());
207+
Set<Klass> result = new HashSet<>();
205208
for (RegistryEntry value : bootClassRegistry.classes.values()) {
206209
result.add(value.klass());
207210
}
211+
if (includeHidden) {
212+
addAllHiddenKlasses(bootClassRegistry, result);
213+
}
214+
// include array classes
215+
result.addAll(getLoadedArrayClasses(result));
216+
// include primitive array classes, but not the primitive classes themselves
217+
result.addAll(getLoadedArrayClasses(Arrays.asList(context.getMeta().PRIMITIVE_KLASSES)));
208218
return result;
209219
}
210220
ClassRegistry classRegistry = getClassRegistry(classLoader);
211-
return classRegistry == null ? Collections.emptyList() : classRegistry.getLoadedKlasses();
221+
if (classRegistry == null) {
222+
return Collections.emptySet();
223+
}
224+
Set<Klass> result = classRegistry.getLoadedKlasses();
225+
if (includeHidden) {
226+
addAllHiddenKlasses(classRegistry, result);
227+
}
228+
229+
// include loaded array classes
230+
result.addAll(getLoadedArrayClasses(result));
231+
return result;
232+
}
233+
234+
private static void addAllHiddenKlasses(ClassRegistry registry, Set<Klass> result) {
235+
synchronized (registry.getStrongHiddenClassRegistrationLock()) {
236+
if (registry.strongHiddenKlasses != null) {
237+
result.addAll(registry.strongHiddenKlasses);
238+
}
239+
if (registry.getHiddenKlasses() != null) {
240+
result.addAll(registry.getHiddenKlasses());
241+
}
242+
}
212243
}
213244

214245
@TruffleBoundary
@@ -234,21 +265,29 @@ public Klass[] findLoadedClassAny(Symbol<Type> type) {
234265
}
235266

236267
@TruffleBoundary
237-
public List<Klass> getAllLoadedClasses() {
238-
ArrayList<Klass> list = new ArrayList<>();
239-
// add classes from boot registry
240-
for (RegistryEntry entry : bootClassRegistry.classes.values()) {
241-
list.add(entry.klass());
242-
}
268+
public Set<Klass> getAllLoadedClasses() {
269+
// first add classes from boot registry
270+
HashSet<Klass> set = new HashSet<>(getLoadedClassesByLoader(StaticObject.NULL, true));
271+
243272
// add classes from all other registries
244273
synchronized (weakClassLoaderSet) {
245274
for (StaticObject classLoader : weakClassLoaderSet) {
246-
for (RegistryEntry entry : getClassRegistry(classLoader).classes.values()) {
247-
list.add(entry.klass());
248-
}
275+
set.addAll(getLoadedClassesByLoader(classLoader, true));
249276
}
250277
}
251-
return list;
278+
return set;
279+
}
280+
281+
private static Set<Klass> getLoadedArrayClasses(Collection<Klass> elementalKlasses) {
282+
Set<Klass> result = new HashSet<>();
283+
for (Klass elementalKlass : elementalKlasses) {
284+
ArrayKlass arrayKlass = elementalKlass.getArrayKlass(false);
285+
while (arrayKlass != null) {
286+
result.add(arrayKlass);
287+
arrayKlass = arrayKlass.getArrayKlass(false);
288+
}
289+
}
290+
return result;
252291
}
253292

254293
public ModuleRef[] getAllModuleRefs() {
@@ -298,7 +337,7 @@ public Klass loadKlass(Symbol<Type> type, @JavaType(ClassLoader.class) StaticObj
298337
if (elemental == null) {
299338
return null;
300339
}
301-
return elemental.getArrayClass(TypeSymbols.getArrayDimensions(type));
340+
return elemental.getArrayKlass(TypeSymbols.getArrayDimensions(type));
302341
}
303342
ClassRegistry registry = getClassRegistry(classLoader);
304343
return registry.loadKlass(context, type, protectionDomain);

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ClassRegistry.java

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,11 @@
2424

2525
import java.util.ArrayList;
2626
import java.util.Collection;
27-
import java.util.List;
27+
import java.util.Collections;
28+
import java.util.HashSet;
2829
import java.util.Objects;
30+
import java.util.Set;
31+
import java.util.WeakHashMap;
2932
import java.util.concurrent.ConcurrentHashMap;
3033
import java.util.concurrent.locks.ReadWriteLock;
3134
import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -281,13 +284,19 @@ public byte[] getRetransformBytes(Klass klass) {
281284
* reclaimed, while not appearing in the actual registry. This field simply keeps those hidden
282285
* classes strongly reachable from the class registry.
283286
*/
284-
private volatile Collection<Klass> strongHiddenKlasses = null;
287+
volatile Collection<Klass> strongHiddenKlasses = null;
285288

286-
private Object getStrongHiddenClassRegistrationLock() {
289+
/**
290+
* Hidden classes must be reachable until they're unloaded, because JDWP and JVMTI must be able
291+
* to query all classes.
292+
*/
293+
private volatile WeakHashMap<Klass, Void> hiddenKlasses = null;
294+
295+
Object getStrongHiddenClassRegistrationLock() {
287296
return this;
288297
}
289298

290-
private void registerStrongHiddenClass(Klass klass) {
299+
private void registerStrongHiddenKlass(Klass klass) {
291300
synchronized (getStrongHiddenClassRegistrationLock()) {
292301
if (strongHiddenKlasses == null) {
293302
strongHiddenKlasses = new ArrayList<>();
@@ -296,6 +305,19 @@ private void registerStrongHiddenClass(Klass klass) {
296305
}
297306
}
298307

308+
private void registerHiddenKlass(Klass klass) {
309+
synchronized (getStrongHiddenClassRegistrationLock()) {
310+
if (hiddenKlasses == null) {
311+
hiddenKlasses = new WeakHashMap<>();
312+
}
313+
hiddenKlasses.put(klass, null);
314+
}
315+
}
316+
317+
public Set<Klass> getHiddenKlasses() {
318+
return hiddenKlasses != null ? hiddenKlasses.keySet() : Collections.emptySet();
319+
}
320+
299321
protected ClassRegistry(long loaderID, ArchivedRegistryData archivedData) {
300322
this.loaderID = loaderID;
301323
if (archivedData != null) {
@@ -332,7 +354,7 @@ Klass loadKlass(EspressoContext context, Symbol<Type> type, StaticObject protect
332354
if (elemental == null) {
333355
return null;
334356
}
335-
return elemental.getArrayClass(TypeSymbols.getArrayDimensions(type));
357+
return elemental.getArrayKlass(TypeSymbols.getArrayDimensions(type));
336358
}
337359

338360
loadKlassCountInc();
@@ -373,8 +395,8 @@ Klass loadKlass(EspressoContext context, Symbol<Type> type, StaticObject protect
373395
public abstract @JavaType(ClassLoader.class) StaticObject getClassLoader();
374396

375397
@TruffleBoundary
376-
public List<Klass> getLoadedKlasses() {
377-
ArrayList<Klass> klasses = new ArrayList<>(classes.size());
398+
Set<Klass> getLoadedKlasses() {
399+
HashSet<Klass> klasses = new HashSet<>(classes.size());
378400
for (ClassRegistries.RegistryEntry entry : classes.values()) {
379401
klasses.add(entry.klass());
380402
}
@@ -388,7 +410,7 @@ public Klass findLoadedKlass(ClassLoadingEnv env, Symbol<Type> type) {
388410
if (elementalKlass == null) {
389411
return null;
390412
}
391-
return elementalKlass.getArrayClass(TypeSymbols.getArrayDimensions(type));
413+
return elementalKlass.getArrayKlass(TypeSymbols.getArrayDimensions(type));
392414
}
393415
ClassRegistries.RegistryEntry entry = classes.get(type);
394416
if (entry == null) {
@@ -456,7 +478,9 @@ public ObjectKlass defineKlass(EspressoContext context, Symbol<Type> typeOrNull,
456478
if (info.addedToRegistry()) {
457479
registerKlass(klass, type, beforeRetransformBytes);
458480
} else if (info.isStrongHidden()) {
459-
registerStrongHiddenClass(klass);
481+
registerStrongHiddenKlass(klass);
482+
} else {
483+
registerHiddenKlass(klass);
460484
}
461485
return klass;
462486
}

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/Klass.java

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -945,18 +945,22 @@ private boolean checkTypeName(@JavaType(String.class) StaticObject computedTypeN
945945
/**
946946
* Gets the array class type representing an array with elements of this type.
947947
*
948-
* This method is equivalent to {@link Klass#getArrayClass()}.
948+
* This method is equivalent to {@link Klass#getArrayKlass()}.
949949
*/
950950
public final ArrayKlass array() {
951-
return getArrayClass();
951+
return getArrayKlass();
952952
}
953953

954954
/**
955955
* Gets the array class type representing an array with elements of this type.
956956
*/
957-
public final ArrayKlass getArrayClass() {
957+
public final ArrayKlass getArrayKlass() {
958+
return getArrayKlass(true);
959+
}
960+
961+
public final ArrayKlass getArrayKlass(boolean create) {
958962
ArrayKlass result = this.arrayKlass;
959-
if (result == null) {
963+
if (result == null && create) {
960964
CompilerDirectives.transferToInterpreterAndInvalidate();
961965
result = createArrayKlass();
962966
}
@@ -972,22 +976,33 @@ private synchronized ArrayKlass createArrayKlass() {
972976
return result;
973977
}
974978

975-
@Override
976-
public ArrayKlass getArrayClass(int dimensions) {
979+
public ArrayKlass getArrayKlass(int dimensions) {
980+
return getArrayKlass(dimensions, true);
981+
}
982+
983+
private ArrayKlass getArrayKlass(int dimensions, boolean create) {
977984
assert dimensions > 0;
978-
ArrayKlass array = array();
985+
ArrayKlass array = getArrayKlass(create);
979986

980987
// Careful with of impossible void[].
981988
if (array == null) {
982989
return null;
983990
}
984991

985992
for (int i = 1; i < dimensions; ++i) {
986-
array = array.getArrayClass();
993+
array = array.getArrayKlass(create);
994+
if (array == null) {
995+
return null;
996+
}
987997
}
988998
return array;
989999
}
9901000

1001+
@Override
1002+
public ArrayKlass getArrayClassNoCreate(int dimensions) {
1003+
return getArrayKlass(dimensions, false);
1004+
}
1005+
9911006
@Override
9921007
public final boolean equals(Object that) {
9931008
return this == that;
@@ -1346,7 +1361,7 @@ public StaticObject allocateReferenceArray(int length, IntFunction<StaticObject>
13461361
for (int i = 0; i < array.length; ++i) {
13471362
array[i] = generator.apply(i);
13481363
}
1349-
return meta.getAllocator().wrapArrayAs(getArrayClass(), array);
1364+
return meta.getAllocator().wrapArrayAs(getArrayKlass(), array);
13501365
}
13511366

13521367
// region Lookup

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/jvmci/JVMCIUtils.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public static Klass findObjectType(Symbol<Type> symbol, ObjectKlass accessingKla
6969
if (elemental == null) {
7070
return null;
7171
}
72-
return elemental.getArrayClass(TypeSymbols.getArrayDimensions(symbol));
72+
return elemental.getArrayKlass(TypeSymbols.getArrayDimensions(symbol));
7373
} else {
7474
return findInstanceType(symbol, accessingKlass, resolve, meta);
7575
}

0 commit comments

Comments
 (0)