Path: blob/master/test/jdk/jdk/jfr/event/oldobject/OldObjects.java
44021 views
/*1* Copyright (c) 2015, 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 jdk.jfr.event.oldobject;2324import java.io.IOException;25import java.util.List;26import java.util.function.Predicate;2728import jdk.jfr.Recording;29import jdk.jfr.consumer.RecordedClass;30import jdk.jfr.consumer.RecordedEvent;31import jdk.jfr.consumer.RecordedFrame;32import jdk.jfr.consumer.RecordedMethod;33import jdk.jfr.consumer.RecordedObject;34import jdk.jfr.consumer.RecordedStackTrace;35import jdk.test.lib.jfr.Events;3637/**38* Utility class to perform Old Object provocation/detection and39* stack trace/object verification for the Old Object Sample JFR event40*/41final public class OldObjects {4243public static final int MIN_SIZE = 99901; // prime number44public final static int LEAK_CONTEXT = 100; // length of chain assiociated with the object sample45public final static int ROOT_CONTEXT = 100; // length of chain assoicated with the root46public final static int MAX_CHAIN_LENGTH = LEAK_CONTEXT + ROOT_CONTEXT; // the VM should not construct chains longer than this4748private static String[] getFrames(String expectedFrame) {49if (expectedFrame != null) {50return new String[] { expectedFrame };51} else {52return null;53}54}5556/**57*58* @param r59* A recording60* @param expectedFrame61* A frame that must be found on the stack. Null if no check is required.62* @param fieldType63* The object type (of the field). Null if no check is required.64* @param fieldName65* The field name. Null if no check is required.66* @param referrerType67* The class name. Null if no check is required.68* @param minDuration69* The minimum duration of the event, -1 if not applicable.70* @return The count of matching events71* @throws IOException72*/73public static long countMatchingEvents(Recording r, String expectedFrame, Class<?> fieldType, String fieldName, Class<?> referrerType, long minDuration) throws IOException {74return countMatchingEvents(r, getFrames(expectedFrame), fieldType, fieldName, referrerType, minDuration);75}7677/**78* Gets the OldObjectSample events from the provided recording through a dump79* and counts how many events matches the provided parameters.80*81* @param r82* A recording83* @param expectedStack84* Some frames that must be found on the stack. Null if no check is required.85* @param fieldType86* The object type (of the field). Null if no check is required.87* @param fieldName88* The field name. Null if no check is required.89* @param referrerType90* The class name. Null if no check is required.91* @param minDuration92* The minimum duration of the event, -1 if not applicable.93* @return The count of matching events94* @throws IOException95*/96public static long countMatchingEvents(Recording r, String[] expectedStack, Class<?> fieldType, String fieldName, Class<?> referrerType, long minDuration) throws IOException {97return countMatchingEvents(Events.fromRecording(r), fieldType, fieldName, referrerType, minDuration, expectedStack);98}99100/**101*102* @param events103* A list of RecordedEvent.104* @param expectedFrame105* A frame that must be found on the stack. Null if no check is required.106* @param fieldType107* The object type (of the field). Null if no check is required.108* @param fieldName109* The field name. Null if no check is required.110* @param referrerType111* The class name. Null if no check is required.112* @param minDuration113* The minimum duration of the event, -1 if not applicable.114* @return The count of matching events115* @throws IOException116*/117public static long countMatchingEvents(List<RecordedEvent> events, String expectedFrame, Class<?> fieldType, String fieldName, Class<?> referrerType, long minDuration) throws IOException {118return countMatchingEvents(events, fieldType, fieldName, referrerType, minDuration, getFrames(expectedFrame));119}120121/**122*123* @param events124* The list of events to find matching events in125* @param expectedStack126* Some frames that must be found on the stack. Null if no check is required.127* @param fieldType128* The object type (of the field). Null if no check is required.129* @param fieldName130* The field name. Null if no check is required.131* @param referrerType132* The class name. Null if no check is required.133* @param minDuration134* The minimum duration of the event, -1 if not applicable.135* @return The count of matching events136* @throws IOException137*/138public static long countMatchingEvents(List<RecordedEvent> events, Class<?> fieldType, String fieldName, Class<?> referrerType, long minDuration, String... expectedStack) throws IOException {139String currentThread = Thread.currentThread().getName();140return events.stream()141.filter(hasJavaThread(currentThread))142.filter(fieldIsType(fieldType))143.filter(hasFieldName(fieldName))144.filter(isReferrerType(referrerType))145.filter(durationAtLeast(minDuration))146.filter(hasStackTrace(expectedStack))147.count();148}149150private static Predicate<RecordedEvent> hasJavaThread(String expectedThread) {151if (expectedThread != null) {152return e -> e.getThread() != null && expectedThread.equals(e.getThread().getJavaName());153} else {154return e -> true;155}156}157158private static Predicate<RecordedEvent> hasStackTrace(String[] expectedStack) {159if (expectedStack != null) {160return e -> matchingStackTrace(e.getStackTrace(), expectedStack);161} else {162return e -> true;163}164}165166private static Predicate<RecordedEvent> fieldIsType(Class<?> fieldType) {167if (fieldType != null) {168return e -> e.hasField("object.type") && ((RecordedClass) e.getValue("object.type")).getName().equals(fieldType.getName());169} else {170return e -> true;171}172}173174private static Predicate<RecordedEvent> hasFieldName(String fieldName) {175if (fieldName != null) {176return e -> {177RecordedObject referrer = e.getValue("object.referrer");178return referrer != null ? referrer.hasField("field.name") && referrer.getValue("field.name").equals(fieldName) : false;179};180} else {181return e -> true;182}183}184185private static Predicate<RecordedEvent> isReferrerType(Class<?> referrerType) {186if (referrerType != null) {187return e -> {188RecordedObject referrer = e.getValue("object.referrer");189return referrer != null ? referrer.hasField("object.type") &&190((RecordedClass) referrer.getValue("object.type")).getName().equals(referrerType.getName()) : false;191};192} else {193return e -> true;194}195}196197private static Predicate<RecordedEvent> durationAtLeast(long minDurationMs) {198if (minDurationMs > 0) {199return e -> e.getDuration().toMillis() >= minDurationMs;200} else {201return e -> true;202}203}204205public static boolean matchingReferrerClass(RecordedEvent event, String className) {206RecordedObject referrer = event.getValue("object.referrer");207if (referrer != null) {208if (!referrer.hasField("object.type")) {209return false;210}211212String reportedClass = ((RecordedClass) referrer.getValue("object.type")).getName();213if (reportedClass.equals(className)) {214return true;215}216}217return false;218}219220public static String getReferrerFieldName(RecordedEvent event) {221RecordedObject referrer = event.getValue("object.referrer");222return referrer != null && referrer.hasField("field.name") ? referrer.getValue("field.name") : null;223}224225public static boolean matchingStackTrace(RecordedStackTrace stack, String[] expectedStack) {226if (stack == null) {227return false;228}229230List<RecordedFrame> frames = stack.getFrames();231int pos = findFramePos(frames, expectedStack[0]);232233if (pos == -1) {234return false;235}236237for (String expectedFrame : expectedStack) {238RecordedFrame f = frames.get(pos++);239String frame = frameToString(f);240241if (!frame.contains(expectedFrame)) {242return false;243}244}245return true;246}247248private static int findFramePos(List<RecordedFrame> frames, String frame) {249int pos = 0;250for (RecordedFrame f : frames) {251if (frameToString(f).contains(frame)) {252return pos;253}254pos++;255}256return -1;257}258259private static String frameToString(RecordedFrame f) {260RecordedMethod m = f.getMethod();261String methodName = m.getName();262String className = m.getType().getName();263return className + "." + methodName;264}265266public static void validateReferenceChainLimit(RecordedEvent e, int maxLength) {267int length = 0;268RecordedObject object = e.getValue("object");269while (object != null) {270++length;271RecordedObject referrer = object.getValue("referrer");272object = referrer != null ? referrer.getValue("object") : null;273}274if (length > maxLength) {275throw new RuntimeException("Reference chain max length not respected. Found a chain of length " + length);276}277}278}279280281