< prev index next >

test/java/util/logging/Level/CustomLevel.java

Print this page

        

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, 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
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.

@@ -20,16 +20,19 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
 
 import java.io.*;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
 import java.util.*;
 import java.util.logging.*;
 
 /*
  * @test
- * @bug 8026027
+ * @bug 8026027 6543126
  * @summary Test Level.parse to look up custom levels by name and its
  *          localized name
  *
  * @run main/othervm CustomLevel
  */

@@ -39,27 +42,101 @@
         super(name, value, resourceBundleName);
     }
 
     private static final List<Level> levels = new ArrayList<>();
     private static final String RB_NAME = "myresource";
+
+    private static class CustomLevelReference extends WeakReference<Level> {
+        final String name;
+        final int value;
+        final String resourceBundleName;
+        public CustomLevelReference(Level level, ReferenceQueue<Level> queue) {
+            super(level, queue);
+            name = level.getName();
+            value = level.intValue();
+            resourceBundleName = level.getResourceBundleName();
+        }
+
+        @Override
+        public String toString() {
+            return "CustomLevelReference(\"" + name + "\", " + value + ", \""
+                    + resourceBundleName + "\")";
+        }
+    }
+
     public static void main(String[] args) throws Exception {
         setupCustomLevels();
 
         // Level.parse will return the custom Level instance
         ResourceBundle rb = ResourceBundle.getBundle(RB_NAME);
         for (Level level : levels) {
             String name = level.getName();
+            Level l = Level.parse(name);
             if (!name.equals("WARNING") && !name.equals("INFO")) {
                 // custom level whose name doesn't conflict with any standard one
-                checkCustomLevel(Level.parse(name), level);
+                checkCustomLevel(l, level);
+            } else if (l != Level.WARNING && l != Level.INFO
+                    || !name.equals(l.getName())) {
+                throw new RuntimeException("Unexpected level " + formatLevel(l));
             }
+            System.out.println("Level.parse found expected level: "
+                            + formatLevel(l));
             String localizedName = rb.getString(level.getName());
-            Level l = Level.parse(localizedName);
+            l = Level.parse(localizedName);
             if (l != level) {
                 throw new RuntimeException("Unexpected level " + l + " " + l.getClass());
             }
         }
+
+        // Now verify that custom level instances are correctly
+        // garbage collected when no longer referenced
+        ReferenceQueue<Level> queue = new ReferenceQueue<>();
+        while (!levels.isEmpty()) {
+            Level l = levels.stream().findAny().get();
+            CustomLevelReference ref = new CustomLevelReference(l, queue);
+
+            // remove strong references to l
+            levels.remove(l);
+            l = null;
+
+            // Run gc and wait for garbage collection
+            Reference<? extends Level> ref2;
+            do {
+                System.gc();
+                Thread.sleep(100);
+            } while ((ref2 = queue.poll()) == null);
+
+            // Check garbage collected reference
+            if (ref2 != ref) {
+                throw new RuntimeException("Unexpected reference: " + ref2);
+            }
+            System.out.println(ref2 + " garbage collected");
+            final String name = ref.name;
+            try {
+                l = Level.parse(name);
+                if (!name.equals("WARNING") && !name.equals("INFO")
+                        || !name.equals(l.getName())) {
+                    throw new RuntimeException("Unexpected level "
+                            + formatLevel(l));
+                } else {
+                    if (l == Level.WARNING || l == Level.INFO) {
+                        System.out.println("Level.parse found expected level: "
+                                + formatLevel(l));
+                    } else {
+                        throw new RuntimeException("Unexpected level "
+                            + formatLevel(l));
+                    }
+                }
+            } catch (IllegalArgumentException iae) {
+                if (!name.equals("WARNING") && !name.equals("INFO")) {
+                    System.out.println("Level.parse fired expected exception: "
+                            + iae);
+                } else {
+                    throw iae;
+                }
+            }
+        }
     }
 
     private static void setupCustomLevels() throws IOException {
         levels.add(new CustomLevel("EMERGENCY", 1090, RB_NAME));
         levels.add(new CustomLevel("ALERT", 1060, RB_NAME));
< prev index next >