8222422: vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses tests failed with Unexpected Exception: null
authordtitov
Thu, 16 May 2019 11:37:26 -0700
changeset 54907 6bcda7ed24ef
parent 54906 b6ee58ec8814
child 54908 717c4a905f62
8222422: vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses tests failed with Unexpected Exception: null Reviewed-by: dholmes, jcbeyler, cjplummer
src/jdk.jdi/share/classes/com/sun/tools/jdi/ClassLoaderReferenceImpl.java
src/jdk.jdi/share/classes/com/sun/tools/jdi/ClassTypeImpl.java
src/jdk.jdi/share/classes/com/sun/tools/jdi/InterfaceTypeImpl.java
src/jdk.jdi/share/classes/com/sun/tools/jdi/ReferenceTypeImpl.java
src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineImpl.java
--- a/src/jdk.jdi/share/classes/com/sun/tools/jdi/ClassLoaderReferenceImpl.java	Thu May 16 13:34:33 2019 -0400
+++ b/src/jdk.jdi/share/classes/com/sun/tools/jdi/ClassLoaderReferenceImpl.java	Thu May 16 11:37:26 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -59,12 +59,12 @@
 
     public List<ReferenceType> definedClasses() {
         ArrayList<ReferenceType> definedClasses = new ArrayList<>();
-        for (ReferenceType type :  vm.allClasses()) {
+        vm.forEachClass(type -> {
             if (type.isPrepared() &&
-                equals(type.classLoader())) {
+                    equals(type.classLoader())) {
                 definedClasses.add(type);
             }
-        }
+        });
         return definedClasses;
     }
 
--- a/src/jdk.jdi/share/classes/com/sun/tools/jdi/ClassTypeImpl.java	Thu May 16 13:34:33 2019 -0400
+++ b/src/jdk.jdi/share/classes/com/sun/tools/jdi/ClassTypeImpl.java	Thu May 16 11:37:26 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -110,16 +110,15 @@
 
     public List<ClassType> subclasses() {
         List<ClassType> subs = new ArrayList<>();
-        for (ReferenceType refType : vm.allClasses()) {
+        vm.forEachClass(refType -> {
             if (refType instanceof ClassType) {
                 ClassType clazz = (ClassType)refType;
                 ClassType superclass = clazz.superclass();
                 if ((superclass != null) && superclass.equals(this)) {
-                    subs.add((ClassType)refType);
+                    subs.add(clazz);
                 }
             }
-        }
-
+        });
         return subs;
     }
 
--- a/src/jdk.jdi/share/classes/com/sun/tools/jdi/InterfaceTypeImpl.java	Thu May 16 13:34:33 2019 -0400
+++ b/src/jdk.jdi/share/classes/com/sun/tools/jdi/InterfaceTypeImpl.java	Thu May 16 11:37:26 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -77,27 +77,27 @@
 
     public List<InterfaceType> subinterfaces() {
         List<InterfaceType> subs = new ArrayList<InterfaceType>();
-        for (ReferenceType refType : vm.allClasses()) {
+        vm.forEachClass(refType -> {
             if (refType instanceof InterfaceType) {
                 InterfaceType interfaze = (InterfaceType)refType;
                 if (interfaze.isPrepared() && interfaze.superinterfaces().contains(this)) {
                     subs.add(interfaze);
                 }
             }
-        }
+        });
         return subs;
     }
 
     public List<ClassType> implementors() {
         List<ClassType> implementors = new ArrayList<ClassType>();
-        for (ReferenceType refType : vm.allClasses()) {
+        vm.forEachClass(refType -> {
             if (refType instanceof ClassType) {
                 ClassType clazz = (ClassType)refType;
                 if (clazz.isPrepared() && clazz.interfaces().contains(this)) {
                     implementors.add(clazz);
                 }
             }
-        }
+        });
         return implementors;
     }
 
--- a/src/jdk.jdi/share/classes/com/sun/tools/jdi/ReferenceTypeImpl.java	Thu May 16 13:34:33 2019 -0400
+++ b/src/jdk.jdi/share/classes/com/sun/tools/jdi/ReferenceTypeImpl.java	Thu May 16 11:37:26 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -607,23 +607,20 @@
     }
 
     public List<ReferenceType> nestedTypes() {
-        List<ReferenceType> all = vm.allClasses();
         List<ReferenceType> nested = new ArrayList<ReferenceType>();
         String outername = name();
         int outerlen = outername.length();
-        Iterator<ReferenceType> iter = all.iterator();
-        while (iter.hasNext()) {
-            ReferenceType refType = iter.next();
+        vm.forEachClass(refType -> {
             String name = refType.name();
             int len = name.length();
             /* The separator is historically '$' but could also be '#' */
             if ( len > outerlen && name.startsWith(outername) ) {
                 char c = name.charAt(outerlen);
-                if ( c =='$' || c== '#' ) {
+                if ( c == '$' || c == '#' ) {
                     nested.add(refType);
                 }
             }
-        }
+        });
         return nested;
     }
 
--- a/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineImpl.java	Thu May 16 13:34:33 2019 -0400
+++ b/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineImpl.java	Thu May 16 11:37:26 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,6 +38,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.function.Consumer;
 
 import com.sun.jdi.BooleanType;
 import com.sun.jdi.BooleanValue;
@@ -57,6 +58,7 @@
 import com.sun.jdi.LongType;
 import com.sun.jdi.LongValue;
 import com.sun.jdi.ModuleReference;
+import com.sun.jdi.ObjectCollectedException;
 import com.sun.jdi.PathSearchingVirtualMachine;
 import com.sun.jdi.PrimitiveType;
 import com.sun.jdi.ReferenceType;
@@ -338,6 +340,27 @@
         return Collections.unmodifiableList(a);
     }
 
+    /**
+     * Performs an action for each loaded type.
+     */
+    public void forEachClass(Consumer<ReferenceType> action) {
+        for (ReferenceType type : allClasses()) {
+            try {
+                action.accept(type);
+            } catch (ObjectCollectedException ex) {
+                // Some classes might be unloaded and garbage collected since
+                // we retrieved the copy of all loaded classes and started
+                // iterating over them. In this case calling methods on such types
+                // might result in com.sun.jdi.ObjectCollectedException
+                // being thrown. We ignore such classes and keep iterating.
+                if ((vm.traceFlags & VirtualMachine.TRACE_OBJREFS) != 0) {
+                    vm.printTrace("ObjectCollectedException was thrown while " +
+                            "accessing unloaded class " + type.name());
+                }
+            }
+        }
+    }
+
     public void
         redefineClasses(Map<? extends ReferenceType, byte[]> classToBytes)
     {