Path: blob/master/test/hotspot/jtreg/vmTestbase/metaspace/stressHierarchy/common/PerformChecksHelper.java
41161 views
/*1* Copyright (c) 2013, 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*/22package metaspace.stressHierarchy.common;2324import java.lang.reflect.InvocationHandler;25import java.lang.reflect.InvocationTargetException;26import java.lang.reflect.Method;27import java.lang.reflect.Proxy;28import java.util.List;2930import metaspace.stressHierarchy.common.classloader.tree.Node;31import metaspace.stressHierarchy.common.classloader.tree.Tree;32import metaspace.stressHierarchy.common.exceptions.ClassNotUnloadedException;33import metaspace.stressHierarchy.common.exceptions.TimeIsOverException;34import nsk.share.test.ExecutionController;35import sun.hotspot.WhiteBox;36import vm.share.gc.TriggerUnloadingHelper;3738public class PerformChecksHelper {3940private static final int NUMBER_OF_HOT_METHOD_CALLS = 100;4142private static WhiteBox wb = WhiteBox.getWhiteBox();4344// This is the number of failed attempts required to deem class unloading failed45private int attemptsLimit = 50;4647// This is the pause between unloading attempts in milliseconds48private long unloadingPause = 1000;4950// This is the number of failed attempts after that pauses will be involved51private int pausesLimit = 5;5253private TriggerUnloadingHelper triggerUnloadingHelper = null;5455private ExecutionController stresser;5657public PerformChecksHelper(TriggerUnloadingHelper triggerUnloadingHelper, int attemptsLimit, long unloadingPause, int pausesLimit) {58this.triggerUnloadingHelper = triggerUnloadingHelper;59if (attemptsLimit != -1) {60this.attemptsLimit = attemptsLimit;61}62if (unloadingPause != -1) {63this.unloadingPause = unloadingPause;64}65if (pausesLimit != -1) {66this.pausesLimit = pausesLimit;67}68System.out.println("attemptsLimit = " + this.attemptsLimit);69System.out.println("unloadingPause = " + this.unloadingPause);70System.out.println("pausesLimit = " + this.pausesLimit);71}7273public void checkLevelReclaimed(Tree tree, int level)74throws IllegalAccessException, InvocationTargetException, InstantiationException, ClassNotUnloadedException, TimeIsOverException {75long attempsCounter = 0;76boolean checkPassed = false;77ClassNotUnloadedException classNotUnloadedException = null;78while (!checkPassed && attempsCounter++ < attemptsLimit) {79if (attempsCounter > pausesLimit && unloadingPause > 0) {80try {81Thread.sleep(unloadingPause);82} catch (InterruptedException e) {83throw new RuntimeException("Somebody dared to interrupt thread while we were waiting after gc provoke");84}85}86try {87checkLevel(tree, level, false);88checkPassed = true;89} catch (ClassNotUnloadedException exception) {90checkPassed = false;91classNotUnloadedException = exception;92triggerUnloadingHelper.triggerUnloading(stresser);93}94}95if (!checkPassed) {96System.out.println("Going to throw classNotUnloadedException. attempsCounter = " + attempsCounter);97throw classNotUnloadedException;98}99100}101102public void checkLevelAlive(Tree tree, int level) throws IllegalAccessException, InvocationTargetException, InstantiationException, ClassNotUnloadedException, TimeIsOverException {103checkLevel(tree, level, true);104}105106private void checkLevel(Tree tree, int level, boolean shouldBeAlive)107throws IllegalAccessException, InvocationTargetException, InstantiationException, ClassNotUnloadedException, TimeIsOverException {108for (Node node : tree.getNodesInLevel(level)) {109for (String className : node.getLoadedClassesNames()) {110checkStresser();111boolean isClassAlive = wb.isClassAlive(className);112if (isClassAlive != shouldBeAlive) {113throw new ClassNotUnloadedException("Failing test! Class: " + className + " shouldBeAlive: " + shouldBeAlive114+ " isClassAlive: " + isClassAlive);115}116}117}118if (shouldBeAlive) {119checkAncestorsAlive(tree, level);120}121}122123private void callMethods(Class<?> clazz)124throws IllegalAccessException, IllegalArgumentException,125InvocationTargetException, InstantiationException {126try {127for (Method m : clazz.getMethods()) {128for (int j = 0; j < NUMBER_OF_HOT_METHOD_CALLS; j++) {129if (m.getName().equals("composeString")) {130m.invoke(clazz.newInstance());131} else if (m.getName().equals("calculate")) {132m.invoke(clazz.newInstance());133} else if (m.getName().equals("calculate2")) {134m.invoke(clazz.newInstance());135}136}137}138} catch (OutOfMemoryError e) {139if (e.getMessage().trim().toLowerCase().contains("metaspace")) {140// avoid string concatenation, which may create more classes.141System.out.println("Got OOME in metaspace in PerformChecksHelper.callMethods(Class clazz). ");142System.out.println("This is possible with -triggerUnloadingByFillingMetaspace");143} else {144throw e;145}146}147}148149private void checkAncestors(Class<?> clazz) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, TimeIsOverException {150for (; clazz != null; clazz = clazz.getSuperclass()) {151checkStresser();152if (!clazz.isInterface()) {153//check class154callMethods(clazz);155} else {156//check interface by implementing it157InvocationHandler handler = new InvocationHandler() {158@Override159public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {160return Integer.MIN_VALUE;161}162};163Object instance = Proxy.newProxyInstance(clazz.getClassLoader(), new Class[] {clazz}, handler);164instance.hashCode();165}166if (!wb.isClassAlive(clazz.getName())) {167throw new RuntimeException("Test failed in method checkAncestors: class "168+ clazz.getName() + " should be alive");169}170}171}172173private void checkAncestorsAlive(Tree tree, int level)174throws IllegalAccessException, InvocationTargetException,175InstantiationException, IllegalArgumentException, TimeIsOverException {176List<Node> bottomLevel = tree.getNodesInLevel(level);177if (bottomLevel.isEmpty()) {178throw new RuntimeException("Failing test because of test bug: no nodes in bottom level");179}180for (Node node : bottomLevel) {181if (node.getLoadedClasses() == null || node.getLoadedClasses().isEmpty()) {182throw new RuntimeException("Failing test because of test bug: no classes loaded by node " + node);183}184for (Class<?> clazz : node.getLoadedClasses()) {185checkAncestors(clazz);186}187}188}189190public void setStresser(ExecutionController stresser) {191this.stresser = stresser;192}193194private void checkStresser() throws TimeIsOverException {195if (stresser == null) {196throw new RuntimeException("Test bug. Wrong usage of PerformChecksHelper. Stresser was not set.");197}198if (!stresser.continueExecution()) {199throw new TimeIsOverException();200}201}202203204}205206207