List<ReferenceType> (ReferenceType refType) { List<ReferenceType> nestedTypes = myNestedClassesCache.get(refType); if (nestedTypes == null) { List<ReferenceType> list = Collections.emptyList(); try { list = refType.nestedTypes(); } catch (Throwable e) { // sometimes some strange errors are thrown from JDI. Do not crash debugger because of this. // Example: //java.lang.StringIndexOutOfBoundsException: String index out of range: 487700285 // at java.lang.String.checkBounds(String.java:375) // at java.lang.String.<init>(String.java:415) // at com.sun.tools.jdi.PacketStream.readString(PacketStream.java:392) // at com.sun.tools.jdi.JDWP$VirtualMachine$AllClassesWithGeneric$ClassInfo.<init>(JDWP.java:1644) LOG.info(e); } if (!list.isEmpty()) { final Set<ReferenceType> candidates = new HashSet<>(); final ClassLoaderReference outerLoader = refType.classLoader(); for (ReferenceType nested : list) { try { if (Objects.equals(outerLoader, nested.classLoader())) { candidates.add(nested); } } catch (ObjectCollectedException ignored) { } } if (!candidates.isEmpty()) { // keep only direct nested types final Set<ReferenceType> nested2 = new HashSet<>(); for (final ReferenceType candidate : candidates) { nested2.addAll(nestedTypes(candidate)); } candidates.removeAll(nested2); } nestedTypes = candidates.isEmpty() ? Collections.emptyList() : new ArrayList<>(candidates); } else { nestedTypes = Collections.emptyList(); } myNestedClassesCache.put(refType, nestedTypes); } return nestedTypes; }