Path: blob/master/test/hotspot/jtreg/vmTestbase/metaspace/staticReferences/StaticReferences.java
41155 views
/*1* Copyright (c) 2013, 2021, 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 randomness26* @modules java.base/jdk.internal.misc:+open27*28* @summary converted from VM Testbase metaspace/staticReferences.29* VM Testbase keywords: [nonconcurrent, javac, no_cds]30*31* @requires vm.opt.final.ClassUnloading32* @library /vmTestbase /test/lib33* @build sun.hotspot.WhiteBox34* @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox35* @run main/othervm36* -Xmx800m37* -Xbootclasspath/a:.38* -XX:+UnlockDiagnosticVMOptions39* -XX:+WhiteBoxAPI40* StaticReferences41*/4243import java.lang.invoke.MethodHandles;44import java.lang.invoke.MethodHandles.Lookup;45import java.lang.ref.WeakReference;46import java.lang.ref.Reference;47import java.lang.reflect.Field;48import java.lang.reflect.Modifier;49import java.util.HashMap;50import java.util.LinkedList;51import java.util.List;52import java.util.Map;53import java.util.Random;5455import vm.share.InMemoryJavaCompiler;56import nsk.share.gc.GCTestBase;57import nsk.share.test.ExecutionController;58import nsk.share.test.Stresser;59import nsk.share.test.TestBase;60import nsk.share.test.Tests;61import vm.share.gc.TriggerUnloadingHelper;62import vm.share.gc.TriggerUnloadingWithWhiteBox;6364/**65* Test checks that static fields will be initialized in new loaded class. Test performs in loop the following routine:66* 1.) Load class either by regular classloader or by defineHiddenClass.67* 2.) Trigger unloading. Class must be alive. Next step will check that static fields were not lost.68* 3.) Change static fields.69* 4.) Unload class.70* 5.) Load class again as in step 1.71* 6.) Check that static fields were initialized.72*/73@SuppressWarnings("rawtypes")74public class StaticReferences extends GCTestBase {7576private static final int UNLOADING_ATTEMPTS_LIMIT = 50;7778private static final Object[] NO_CP_PATCHES = new Object[0];7980private static String[] args;8182private static final int LIMIT = 20;8384private List<Object> keepAlive = new LinkedList<Object>();8586private Random random;8788private TriggerUnloadingHelper triggerUnloadingHelper = new TriggerUnloadingWithWhiteBox();8990private String[] typesArray = new String[] {"Object object", "boolean boolean", "byte byte", "char char", "double double", "float float", "int int", "long long", "short short"};9192public static void main(String[] args) {93StaticReferences.args = args;94Tests.runTest(new StaticReferences(), args);95}9697@Override98public void run() {99random = new Random(runParams.getSeed());100ExecutionController stresser = new Stresser(args);101stresser.start(1);102103// Generate and compile classes104List<byte[]> bytecodeList = new LinkedList<byte[]>();105int[] fieldQuantities = new int[9];106long startTimeStamp = System.currentTimeMillis();107for (int i = 0; i < LIMIT; i++) {108if (!stresser.continueExecution()) {109return;110}111for (int j = 0; j < fieldQuantities.length; j++) {112fieldQuantities[j] = 1 + random.nextInt(20);113}114bytecodeList.add(generateAndCompile(fieldQuantities));115}116log.info("Compilation finished in " + ((System.currentTimeMillis() - startTimeStamp)/1000/60.0) + " minutes ");117118// Core of test119for (byte[] classBytecode : bytecodeList) {120boolean hidden = random.nextBoolean();121122log.info("Load class first time");123Class clazz = loadClass(classBytecode, hidden);124125log.info("Trigger unloading");126triggerUnloadingHelper.triggerUnloading(stresser);127if (!stresser.continueExecution()) {128return;129}130131log.info("Set up static fields. This will check that static fields are reachable.");132setupFields(clazz);133134log.info("Cleanup references");135Reference<Class> weakReference = new WeakReference<Class>(clazz);136clazz = null;137138log.info("Trigger unloading again");139int numberOfAttemps = 0;140while (weakReference.get() != null && numberOfAttemps < UNLOADING_ATTEMPTS_LIMIT) {141if (!stresser.continueExecution()) {142return;143}144triggerUnloadingHelper.triggerUnloading(stresser);145}146if (numberOfAttemps >= UNLOADING_ATTEMPTS_LIMIT) {147setFailed(true);148throw new RuntimeException("Test failed: was unable to unload class with " + UNLOADING_ATTEMPTS_LIMIT + " attempts.");149}150151log.info("Load class second time");152clazz = loadClass(classBytecode, hidden);153154log.info("check fields reinitialized");155checkStaticFields(clazz);156157keepAlive.add(clazz);158}159}160161private Class loadClass(byte[] classBytecode, boolean hidden) {162Class clazz;163if (hidden) {164Lookup lookup = MethodHandles.lookup();165try {166clazz = lookup.defineHiddenClass(classBytecode, false).lookupClass();167} catch (IllegalAccessException e) {168e.printStackTrace();169throw new RuntimeException(170"Lookup.defineHiddenClass failed: " + e.getMessage());171}172} else {173OneUsageClassloader classloader = new OneUsageClassloader();174clazz = classloader.define(classBytecode);175}176return clazz;177}178179private void checkStaticFields(Class clazz) {180for (Field field : clazz.getFields()) {181try {182if (Modifier.isStatic(field.getModifiers())) {183Class fieldType = field.getType();184if ((fieldType.equals(Object.class) && field.get(null) != null )185|| (fieldType.equals(int.class) && field.getInt(null) != 0)186|| (fieldType.equals(boolean.class) && field.getBoolean(null) != false)187|| (fieldType.equals(char.class) && field.getChar(null) != 0)188|| (fieldType.equals(long.class) && field.getLong(null) != 0)189|| (fieldType.equals(short.class) && field.getShort(null) != 0)190|| (fieldType.equals(float.class) && field.getFloat(null) != 0.0f)191|| (fieldType.equals(double.class) && field.getDouble(null) != 0.0)192|| (fieldType.equals(byte.class) && field.getByte(null) != 0)) {193setFailed(true);194throw new RuntimeException("Failing test: field "195+ field.getName() + " of type "196+ field.getType() + " in class "197+ field.getDeclaringClass().getName()198+ " was not cleared");199}200}201} catch (IllegalArgumentException | IllegalAccessException e) {202e.printStackTrace();203throw new RuntimeException("Was unable to set static field "204+ field.getName() + " of type "205+ field.getType().getName() + " in class "206+ field.getDeclaringClass().getName(), e);207}208}209}210211private byte[] generateAndCompile(int[] fieldQuantities) {212Map<String, CharSequence> sources = new HashMap<String, CharSequence>();213sources.put("A", generateSource(fieldQuantities));214return InMemoryJavaCompiler.compile(sources).values().iterator().next();215}216217private StringBuffer generateSource(int[] fieldQuantities) {218StringBuffer result = new StringBuffer("public class A { \n");219int fieldsCounter = 0;220for (int i = 0; i < typesArray.length; i++) {221for (int j = 0; j < fieldQuantities[i]; j++) {222result.append(" public static " + typesArray[i] + fieldsCounter++ + ";\n");223}224}225result.append(" } ");226return result;227}228229private void setupFields(Class clazz) {230for (Field field : clazz.getFields()) {231try {232if (Modifier.isStatic(field.getModifiers())) {233Class fieldType = field.getType();234if (fieldType.equals(Object.class)) {235field.set(null, this);236} else if (fieldType.equals(int.class)) {237field.setInt(null, 42);238} else if (fieldType.equals(boolean.class)) {239field.setBoolean(null, true);240} else if (fieldType.equals(char.class)) {241field.setChar(null, 'c');242} else if (fieldType.equals(long.class)) {243field.setLong(null, (long) 42);244} else if (fieldType.equals(short.class)) {245field.setShort(null, (short) 42);246} else if (fieldType.equals(float.class)) {247field.setFloat(null, 42.42f);248} else if (fieldType.equals(double.class)) {249field.setDouble(null, 42.42);250} else if (fieldType.equals(byte.class)) {251field.setByte(null, (byte) 42);252}253}254} catch (IllegalArgumentException | IllegalAccessException e) {255e.printStackTrace();256throw new RuntimeException(257"Was unable to set static field " + field.getName()258+ " of type " + field.getType().getName()259+ " in class "260+ field.getDeclaringClass().getName(), e);261}262}263}264265}266267268