Path: blob/master/test/hotspot/jtreg/vmTestbase/gc/gctests/LargeObjects/large001/large001.java
41161 views
/*1* Copyright (c) 2004, 2020, 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/*24* @test25* @key stress randomness26*27* @summary converted from VM Testbase gc/gctests/LargeObjects/large001.28* VM Testbase keywords: [gc, stress, stressopt, nonconcurrent, quick]29* VM Testbase readme:30* DESCRIPTION31* The test checks that Garbage Collector correctly does not throw any32* unexpected exceptions/errors while allocating large objects (classes33* that have more than 65535 fields and classes that have less than 6553534* fields). 65535 of fields is a limitation for JVM (see JVM specification35* Second edition 4.10).36* Since it is impossible to create one class with about 65535 of fields37* (javac cannot compile it), a child class extends a parent class, so the38* fields are devided into two subsets. However, the child class still has39* about 65535 of fields.40* The test starts a number of threads. This number is either set in *.cfg41* file or is calculated by the test itself based on the machine (see42* nsk.share.gc.Algorithms.getThreadsCount() method). As soon as all threads43* are started, each thread begins its checking.44* There are 13 classes to be loaded by each thread. These classes are45* generated by nsk.share.gc.Generator (see its javadoc for more details).46* Each class has a huge number of fields, but this number is less than the JVM47* limitation.48* The test loads the classes with nsk.share.gc.GCClassUnloader class that49* extends nsk.share.ClassUnloader and has a bit different algorith of eating50* heap. As soon as a class is loaded, the test creates an instance of51* it - allocates an object of that type. Then it drops references to the52* class and to the instance and tries to unload the class. The test does not53* expect any exceptions to be thrown.54*55* @library /vmTestbase56* /test/lib57*58* @comment generate and compile nsk.share.gc.newclass.* classes59* @run driver nsk.share.gc.GenClassesBuilder60*61* @run main/othervm62* -XX:-UseGCOverheadLimit63* -Xlog:gc*64* gc.gctests.LargeObjects.large001.large00165* -largeClassesPath classes66* -isOverLimitFields false67* -aggregationDepth 068* -t 169*/7071package gc.gctests.LargeObjects.large001;7273import java.lang.reflect.*;74import java.lang.ref.WeakReference;75import java.util.*;76import nsk.share.TestFailure;777879import nsk.share.gc.*;80import nsk.share.*;8182public class large001 extends ThreadedGCTest {8384// Package of the classes to be loaded85final static String PREFIX = "nsk.share.gc.newclass.";86// A bunch of classes that have number of fields more than JVM limitation87final static String[] LCLASSES = {PREFIX + "private_int_lchild",88PREFIX + "protected_short_lchild",89PREFIX + "public_long_lchild",90PREFIX + "public_Object_lchild",91PREFIX + "static_byte_lchild",92PREFIX + "static_float_lchild",93PREFIX + "transient_boolean_lchild",94PREFIX + "volatile_double_lchild",95PREFIX + "protected_combination_lchild",96PREFIX + "public_combination_lchild",97PREFIX + "static_combination_lchild",98PREFIX + "transient_combination_lchild",99PREFIX + "volatile_combination_lchild"100};101// A bunch of classes that have number of fields less than JVM limitation102final static String[] SCLASSES = {PREFIX + "private_int_schild",103PREFIX + "protected_short_schild",104PREFIX + "public_long_schild",105PREFIX + "public_Object_schild",106PREFIX + "static_byte_schild",107PREFIX + "static_float_schild",108PREFIX + "transient_boolean_schild",109PREFIX + "volatile_double_schild",110PREFIX + "protected_combination_schild",111PREFIX + "public_combination_schild",112PREFIX + "static_combination_schild",113PREFIX + "transient_combination_schild",114PREFIX + "volatile_combination_schild"115};116boolean isOverLimitFields = true;117int aggregationDepth = 0;118String largeClassesPath;119120private class Worker implements Runnable {121122int id;123124public Worker(int id) {125this.id = id;126}127128public void run() {129try {130// Use special ClassUnloader to load/unload classes131ClassUnloader unloader = new ClassUnloader();132String[] classes = isOverLimitFields ? LCLASSES : SCLASSES;133134for (String name : classes) {135// Load the class136log.debug(id + ": Loading class: " + name);137unloader.loadClass(name, largeClassesPath);138log.debug(id + ": Class loaded: " + name);139140Class loadedClass = unloader.getLoadedClass();141Object loadedClassInstance = loadedClass.newInstance();142143log.debug(id + ": Instance of the class: " + loadedClassInstance);144int depth = aggregationDepth;145List<WeakReference> refs = new ArrayList<WeakReference>(depth);146addObjRef(loadedClassInstance, loadedClass, depth, refs);147148// Drop all references to the class and try to unload it149Algorithms.eatMemory(getExecutionController());150log.debug(id + ": Testing non-null after GC force for: " + name);151if (loadedClass == null || loadedClassInstance == null) {152throw new Exception("Null class");153}154verifyObjRef(loadedClassInstance, depth);155for (WeakReference ref : refs) {156if (ref.get() == null) {157throw new Exception("Unexpected null reference");158}159}160refs = null;161loadedClass = null;162loadedClassInstance = null;163164log.debug(id + ": Unloading class: "165+ name);166boolean result = unloader.unloadClass(getExecutionController());167log.debug(id + ": Result of uloading "168+ "class " + name + ": " + result);169}170} catch (OutOfMemoryError oome) {171// just skip if we eat memory in several threads...172// rethrow in the case of one thread173if (runParams.getNumberOfThreads() == 1) {174throw oome;175}176} catch (Throwable t) {177throw new TestFailure("Unexpected exception: ", t);178}179}180181// This method recursively create chain of aggregated objects for given object182public void addObjRef(Object object, Class clazz, int count, List<WeakReference> list) throws Throwable {183if (count == 0) {184return;185}186187Field[] fields = object.getClass().getFields();188for (Field field : fields) {189if (field.getName().startsWith("obj")) {190Object addedObject = clazz.newInstance();191field.set(object, addedObject);192System.out.println("Added field " + field.getName() + " .... " + count);193addObjRef(addedObject, clazz, count - 1, list);194list.add(new WeakReference<Object>(addedObject));195}196}197}198199// This method recursively verfiy chain of aggregated objects for given object.200// Throws null pointer exception of objP/C field is null201public void verifyObjRef(Object object, int count) throws Throwable {202if (count == 0) {203return;204}205206Field[] fields = object.getClass().getFields();207for (Field field : fields) {208if (field.getName().startsWith("obj")) {209Object obj = field.get(object);210verifyObjRef(obj, count - 1);211}212}213}214}215216public large001(String[] args) {217for (int i = 0; i < args.length; i++) {218if (args[i].equals("-largeClassesPath")) {219largeClassesPath = args[++i];220} else if (args[i].equals("-isOverLimitFields")) {221isOverLimitFields = Boolean.getBoolean(args[++i]);222} else if (args[i].equals("-aggregationDepth")) {223aggregationDepth = Integer.parseInt(args[++i]);224}225}226if (largeClassesPath == null || largeClassesPath.length() == 0) {227throw new TestFailure("No classpath for large classes is given");228}229}230231@Override232protected Runnable createRunnable(int i) {233return new Worker(i);234}235236@Override237public void run() {238if (isOverLimitFields) {239log.debug("Loading classes that have number "240+ "of fields over limitation (more "241+ "than 65535)");242} else {243log.debug("Loading classes that have number "244+ "of fields under limitation (less "245+ "than 65535)");246}247super.run();248}249250public static void main(String args[]) {251GC.runTest(new large001(args), args);252}253}254255256