8218700: infinite loop in HotSpotJVMCIMetaAccessContext.fromClass after OutOfMemoryError
authordlong
Thu, 25 Apr 2019 13:35:34 -0700
changeset 54733 28dd27202591
parent 54732 2d012a75d35c
child 54734 e8f1b9fc82cc
8218700: infinite loop in HotSpotJVMCIMetaAccessContext.fromClass after OutOfMemoryError Reviewed-by: never, kvn
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java
test/hotspot/jtreg/ProblemList-graal.txt
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java	Mon May 06 20:05:19 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java	Thu Apr 25 13:35:34 2019 -0700
@@ -383,7 +383,25 @@
     /**
      * Cache for speeding up {@link #fromClass(Class)}.
      */
-    @NativeImageReinitialize private volatile ClassValue<WeakReference<HotSpotResolvedJavaType>> resolvedJavaType;
+    @NativeImageReinitialize private volatile ClassValue<WeakReferenceHolder<HotSpotResolvedJavaType>> resolvedJavaType;
+
+    /**
+     * To avoid calling ClassValue.remove to refresh the weak reference, which
+     * under certain circumstances can lead to an infinite loop, we use a
+     * permanent holder with a mutable field that we refresh.
+     */
+    private static class WeakReferenceHolder<T> {
+        private volatile WeakReference<T> ref;
+        WeakReferenceHolder(T value) {
+            set(value);
+        }
+        void set(T value) {
+            ref = new WeakReference<T>(value);
+        }
+        T get() {
+            return ref.get();
+        }
+    };
 
     @NativeImageReinitialize private HashMap<Long, WeakReference<ResolvedJavaType>> resolvedJavaTypes;
 
@@ -485,27 +503,25 @@
         if (resolvedJavaType == null) {
             synchronized (this) {
                 if (resolvedJavaType == null) {
-                    resolvedJavaType = new ClassValue<WeakReference<HotSpotResolvedJavaType>>() {
+                    resolvedJavaType = new ClassValue<WeakReferenceHolder<HotSpotResolvedJavaType>>() {
                         @Override
-                        protected WeakReference<HotSpotResolvedJavaType> computeValue(Class<?> type) {
-                            return new WeakReference<>(createClass(type));
+                        protected WeakReferenceHolder<HotSpotResolvedJavaType> computeValue(Class<?> type) {
+                            return new WeakReferenceHolder<>(createClass(type));
                         }
                     };
                 }
             }
         }
-        HotSpotResolvedJavaType javaType = null;
-        while (javaType == null) {
-            WeakReference<HotSpotResolvedJavaType> type = resolvedJavaType.get(javaClass);
-            javaType = type.get();
-            if (javaType == null) {
-                /*
-                 * If the referent has become null, clear out the current value and let computeValue
-                 * above create a new value. Reload the value in a loop because in theory the
-                 * WeakReference referent can be reclaimed at any point.
-                 */
-                resolvedJavaType.remove(javaClass);
-            }
+
+        WeakReferenceHolder<HotSpotResolvedJavaType> ref = resolvedJavaType.get(javaClass);
+        HotSpotResolvedJavaType javaType = ref.get();
+        if (javaType == null) {
+            /*
+             * If the referent has become null, create a new value and
+             * update cached weak reference.
+             */
+            javaType = createClass(javaClass);
+            ref.set(javaType);
         }
         return javaType;
     }
--- a/test/hotspot/jtreg/ProblemList-graal.txt	Mon May 06 20:05:19 2019 -0700
+++ b/test/hotspot/jtreg/ProblemList-graal.txt	Thu Apr 25 13:35:34 2019 -0700
@@ -210,8 +210,6 @@
 serviceability/tmtools/jstat/GcCapacityTest.java                              8196611 generic-all
 serviceability/jvmti/HeapMonitor/MyPackage/HeapMonitorMultiArrayTest.java     8196611 generic-all
 
-vmTestbase/gc/lock/jvmti/alloc/jvmtialloclock02/TestDescription.java          8218700 generic-all
-
 vmTestbase/nsk/jdb/unmonitor/unmonitor001/unmonitor001.java                   8218701 generic-all
 
 vmTestbase/nsk/jdb/clear/clear003/clear003.java                               8218701 generic-all