Path: blob/master/test/jdk/javax/management/mxbean/LeakTest.java
41149 views
/*1* Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/* @test24* @bug 648224725* @summary Test that creating MXBeans does not introduce memory leaks.26* @requires vm.opt.final.ClassUnloading27* @author Eamonn McManus28*29* @run build LeakTest RandomMXBeanTest MerlinMXBean TigerMXBean30* @run main LeakTest31*/3233/* In this test we create a ClassLoader, then use it to load and run another34* jtreg test. When the other test has completed, we wait for the ClassLoader35* to be garbage-collected. If it has not been gc'd after a reasonable36* amount of time, then something is keeping a reference to the ClassLoader,37* which implies a memory leak.38*39* This test can be applied to any jtreg test, not just the MXBean tests.40*/4142import java.io.File;43import java.lang.ref.Reference;44import java.lang.ref.ReferenceQueue;45import java.lang.ref.WeakReference;46import java.lang.reflect.Method;47import java.net.URL;48import java.net.URLClassLoader;49import java.nio.file.Paths;5051public class LeakTest {52/* Ideally we would include MXBeanTest in the list of tests, since it53* has fairly complete coverage. However, the ClassLoader fails to be54* gc'd when we do that, and I am unable to figure out why. Examining55* a heap dump shows only weak references to the ClassLoader. I suspect56* something is wrong in the internals of the reflection classes, used57* quite heavily by MXBeanTest.58*/59// private static Class<?>[] otherTests = {MXBeanTest.class};6061private static Class<?>[] otherTests = {RandomMXBeanTest.class};6263// This class just makes it easier for us to spot our loader in heap dumps64private static class ShadowClassLoader extends URLClassLoader {65ShadowClassLoader(URL[] urls, ClassLoader parent) {66super(urls, parent);67}68}6970public static void main(String[] args) throws Exception {71System.out.println("Testing that no references are held to ClassLoaders " +72"by caches in the MXBean infrastructure");73for (Class<?> testClass : otherTests)74test(testClass);75if (failure != null)76throw new Exception("CLASSLOADER LEAK TEST FAILED: " + failure);77System.out.println("CLASSLOADER LEAK TEST PASSED");78if (args.length > 0) {79System.out.println("Waiting for input");80System.in.read();81}82}8384private static void test(Class<?> originalTestClass) throws Exception {85System.out.println();86System.out.println("TESTING " + originalTestClass.getName());87WeakReference<ClassLoader> wr = testShadow(originalTestClass);88System.out.println("Test passed, waiting for ClassLoader to disappear");89long deadline = System.currentTimeMillis() + 20*1000;90Reference<? extends ClassLoader> ref;91while (wr.get() != null && System.currentTimeMillis() < deadline) {92System.gc();93Thread.sleep(100);94}95if (wr.get() != null)96fail(originalTestClass.getName() + " kept ClassLoader reference");97}9899private static WeakReference<ClassLoader>100testShadow(Class<?> originalTestClass) throws Exception {101String[] cpaths = System.getProperty("test.classes", ".")102.split(File.pathSeparator);103URL[] urls = new URL[cpaths.length];104for (int i=0; i < cpaths.length; i++) {105urls[i] = Paths.get(cpaths[i]).toUri().toURL();106}107108URLClassLoader shadowLoader =109new ShadowClassLoader(urls, originalTestClass.getClassLoader().getParent());110System.out.println("Shadow loader is " + shadowLoader);111String className = originalTestClass.getName();112Class<?> testClass = Class.forName(className, false, shadowLoader);113if (testClass.getClassLoader() != shadowLoader) {114throw new IllegalArgumentException("Loader didn't work: " +115testClass.getClassLoader() + " != " + shadowLoader);116}117Method main = testClass.getMethod("main", String[].class);118main.invoke(null, (Object) new String[0]);119return new WeakReference<ClassLoader>(shadowLoader);120}121122private static void fail(String why) {123System.out.println("FAILED: " + why);124failure = why;125}126127private static String failure;128}129130131