< prev index next >

test/hotspot/jtreg/runtime/Metaspace/DefineClass.java

Print this page


   1 /*

   2  * Copyright (c) 2017 SAP SE. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /**
  25  * @test
  26  * @bug 8173743
  27  * @requires vm.compMode != "Xcomp"
  28  * @summary Failures during class definition can lead to memory leaks in metaspace
  29  * @library /test/lib
  30  * @run main/othervm test.DefineClass defineClass
  31  * @run main/othervm test.DefineClass defineSystemClass
  32  * @run main/othervm -XX:+UnlockDiagnosticVMOptions
  33                      -XX:+UnsyncloadClass -XX:+AllowParallelDefineClass
  34                      test.DefineClass defineClassParallel
  35  * @run main/othervm -XX:+UnlockDiagnosticVMOptions
  36                      -XX:+UnsyncloadClass -XX:-AllowParallelDefineClass
  37                      test.DefineClass defineClassParallel
  38  * @run main/othervm -XX:+UnlockDiagnosticVMOptions
  39                      -XX:-UnsyncloadClass -XX:+AllowParallelDefineClass
  40                      test.DefineClass defineClassParallel
  41  * @run main/othervm -XX:+UnlockDiagnosticVMOptions
  42                      -XX:-UnsyncloadClass -XX:-AllowParallelDefineClass
  43                      test.DefineClass defineClassParallel
  44  * @run main/othervm -Djdk.attach.allowAttachSelf test.DefineClass redefineClass
  45  * @run main/othervm -Djdk.attach.allowAttachSelf test.DefineClass redefineClassWithError
  46  * @author volker.simonis@gmail.com
  47  */
  48 
  49 package test;
  50 
  51 import java.io.ByteArrayOutputStream;
  52 import java.io.File;
  53 import java.io.FileOutputStream;
  54 import java.io.InputStream;
  55 import java.lang.instrument.ClassDefinition;
  56 import java.lang.instrument.Instrumentation;
  57 import java.lang.management.ManagementFactory;
  58 import java.util.Scanner;
  59 import java.util.concurrent.CountDownLatch;
  60 import java.util.jar.Attributes;
  61 import java.util.jar.JarEntry;
  62 import java.util.jar.JarOutputStream;


 109         private byte[] buf;
 110 
 111         public ParallelLoadingThread(MyParallelClassLoader pcl, byte[] buf, CountDownLatch stop) {
 112             this.pcl = pcl;
 113             this.stop = stop;
 114             this.buf = buf;
 115         }
 116 
 117         public void run() {
 118             try {
 119                 stop.await();
 120             } catch (InterruptedException e) {
 121                 e.printStackTrace();
 122             }
 123             try {
 124                 @SuppressWarnings("unchecked")
 125                 Class<DefineClass> dc = (Class<DefineClass>) pcl.myDefineClass(DefineClass.class.getName(), buf, 0, buf.length);
 126             }
 127             catch (LinkageError jle) {
 128                 // Expected with a parallel capable class loader and
 129                 // -XX:+UnsyncloadClass or -XX:+AllowParallelDefineClass
 130                 pcl.incrementLinkageErrors();
 131             }
 132 
 133         }
 134     }
 135 
 136     static private class MyClassLoader extends ClassLoader {
 137         public Class<?> myDefineClass(String name, byte[] b, int off, int len) throws ClassFormatError {
 138             return defineClass(name, b, off, len, null);
 139         }
 140     }
 141 
 142     static private class MyParallelClassLoader extends ClassLoader {
 143         static {
 144             System.out.println("parallelCapable : " + registerAsParallelCapable());
 145         }
 146         public Class<?> myDefineClass(String name, byte[] b, int off, int len) throws ClassFormatError {
 147             return defineClass(name, b, off, len, null);
 148         }
 149         public synchronized void incrementLinkageErrors() {


 303             System.gc();
 304             System.out.println("System.gc()");
 305             // At least after System.gc() the failed loading attempts should leave no instances around!
 306             printClassStats(1, true);
 307         }
 308         else if ("defineClassParallel".equals(args[0])) {
 309             MyParallelClassLoader pcl = new MyParallelClassLoader();
 310             CountDownLatch stop = new CountDownLatch(1);
 311 
 312             Thread[] threads = new Thread[iterations];
 313             for (int i = 0; i < iterations; i++) {
 314                 (threads[i] = new ParallelLoadingThread(pcl, buf, stop)).start();
 315             }
 316             stop.countDown(); // start parallel class loading..
 317             // ..and wait until all threads loaded the class
 318             for (int i = 0; i < iterations; i++) {
 319                 threads[i].join();
 320             }
 321             System.out.print("Counted " + pcl.getLinkageErrors() + " LinkageErrors ");
 322             System.out.println(pcl.getLinkageErrors() == 0 ?
 323                     "" : "(use -XX:+UnsyncloadClass and/or -XX:+AllowParallelDefineClass to avoid this)");
 324             System.gc();
 325             System.out.println("System.gc()");
 326             // After System.gc() we expect to remain with two instances: one is the initial version which is
 327             // kept alive by this main method and another one in the parallel class loader.
 328             printClassStats(2, true);
 329         }
 330         else if ("redefineClass".equals(args[0])) {
 331             loadInstrumentationAgent(myName, buf);
 332             int index = getStringIndex("AAAAAAAA", buf);
 333             CountDownLatch stop = new CountDownLatch(1);
 334 
 335             Thread[] threads = new Thread[iterations];
 336             for (int i = 0; i < iterations; i++) {
 337                 buf[index] = (byte) ('A' + i + 1); // Change string constant in getID() which is legal in redefinition
 338                 instrumentation.redefineClasses(new ClassDefinition(DefineClass.class, buf));
 339                 DefineClass dc = DefineClass.class.newInstance();
 340                 CountDownLatch start = new CountDownLatch(1);
 341                 (threads[i] = new MyThread(dc, start, stop)).start();
 342                 start.await(); // Wait until the new thread entered the getID() method
 343             }


   1 /*
   2  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright (c) 2017 SAP SE. All rights reserved.
   4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   5  *
   6  * This code is free software; you can redistribute it and/or modify it
   7  * under the terms of the GNU General Public License version 2 only, as
   8  * published by the Free Software Foundation.
   9  *
  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  */
  24 
  25 /**
  26  * @test
  27  * @bug 8173743
  28  * @requires vm.compMode != "Xcomp"
  29  * @summary Failures during class definition can lead to memory leaks in metaspace
  30  * @library /test/lib
  31  * @run main/othervm test.DefineClass defineClass
  32  * @run main/othervm test.DefineClass defineSystemClass
  33  * @run main/othervm -XX:+AllowParallelDefineClass

  34                      test.DefineClass defineClassParallel
  35  * @run main/othervm -XX:-AllowParallelDefineClass







  36                      test.DefineClass defineClassParallel
  37  * @run main/othervm -Djdk.attach.allowAttachSelf test.DefineClass redefineClass
  38  * @run main/othervm -Djdk.attach.allowAttachSelf test.DefineClass redefineClassWithError
  39  * @author volker.simonis@gmail.com
  40  */
  41 
  42 package test;
  43 
  44 import java.io.ByteArrayOutputStream;
  45 import java.io.File;
  46 import java.io.FileOutputStream;
  47 import java.io.InputStream;
  48 import java.lang.instrument.ClassDefinition;
  49 import java.lang.instrument.Instrumentation;
  50 import java.lang.management.ManagementFactory;
  51 import java.util.Scanner;
  52 import java.util.concurrent.CountDownLatch;
  53 import java.util.jar.Attributes;
  54 import java.util.jar.JarEntry;
  55 import java.util.jar.JarOutputStream;


 102         private byte[] buf;
 103 
 104         public ParallelLoadingThread(MyParallelClassLoader pcl, byte[] buf, CountDownLatch stop) {
 105             this.pcl = pcl;
 106             this.stop = stop;
 107             this.buf = buf;
 108         }
 109 
 110         public void run() {
 111             try {
 112                 stop.await();
 113             } catch (InterruptedException e) {
 114                 e.printStackTrace();
 115             }
 116             try {
 117                 @SuppressWarnings("unchecked")
 118                 Class<DefineClass> dc = (Class<DefineClass>) pcl.myDefineClass(DefineClass.class.getName(), buf, 0, buf.length);
 119             }
 120             catch (LinkageError jle) {
 121                 // Expected with a parallel capable class loader and
 122                 // -XX:+AllowParallelDefineClass
 123                 pcl.incrementLinkageErrors();
 124             }
 125 
 126         }
 127     }
 128 
 129     static private class MyClassLoader extends ClassLoader {
 130         public Class<?> myDefineClass(String name, byte[] b, int off, int len) throws ClassFormatError {
 131             return defineClass(name, b, off, len, null);
 132         }
 133     }
 134 
 135     static private class MyParallelClassLoader extends ClassLoader {
 136         static {
 137             System.out.println("parallelCapable : " + registerAsParallelCapable());
 138         }
 139         public Class<?> myDefineClass(String name, byte[] b, int off, int len) throws ClassFormatError {
 140             return defineClass(name, b, off, len, null);
 141         }
 142         public synchronized void incrementLinkageErrors() {


 296             System.gc();
 297             System.out.println("System.gc()");
 298             // At least after System.gc() the failed loading attempts should leave no instances around!
 299             printClassStats(1, true);
 300         }
 301         else if ("defineClassParallel".equals(args[0])) {
 302             MyParallelClassLoader pcl = new MyParallelClassLoader();
 303             CountDownLatch stop = new CountDownLatch(1);
 304 
 305             Thread[] threads = new Thread[iterations];
 306             for (int i = 0; i < iterations; i++) {
 307                 (threads[i] = new ParallelLoadingThread(pcl, buf, stop)).start();
 308             }
 309             stop.countDown(); // start parallel class loading..
 310             // ..and wait until all threads loaded the class
 311             for (int i = 0; i < iterations; i++) {
 312                 threads[i].join();
 313             }
 314             System.out.print("Counted " + pcl.getLinkageErrors() + " LinkageErrors ");
 315             System.out.println(pcl.getLinkageErrors() == 0 ?
 316                     "" : "(use -XX:+AllowParallelDefineClass to avoid this)");
 317             System.gc();
 318             System.out.println("System.gc()");
 319             // After System.gc() we expect to remain with two instances: one is the initial version which is
 320             // kept alive by this main method and another one in the parallel class loader.
 321             printClassStats(2, true);
 322         }
 323         else if ("redefineClass".equals(args[0])) {
 324             loadInstrumentationAgent(myName, buf);
 325             int index = getStringIndex("AAAAAAAA", buf);
 326             CountDownLatch stop = new CountDownLatch(1);
 327 
 328             Thread[] threads = new Thread[iterations];
 329             for (int i = 0; i < iterations; i++) {
 330                 buf[index] = (byte) ('A' + i + 1); // Change string constant in getID() which is legal in redefinition
 331                 instrumentation.redefineClasses(new ClassDefinition(DefineClass.class, buf));
 332                 DefineClass dc = DefineClass.class.newInstance();
 333                 CountDownLatch start = new CountDownLatch(1);
 334                 (threads[i] = new MyThread(dc, start, stop)).start();
 335                 start.await(); // Wait until the new thread entered the getID() method
 336             }


< prev index next >