# HG changeset patch # User egahlin # Date 1574553813 -3600 # Node ID 9fe5d0d4e9c58eb6b7857dc66f03a84b17ce2bec # Parent 2601fc0874be76f0def7fac76fd25f18b647acad 8226897: Provide object age with JFR OldObjectSample event Reviewed-by: mgronlun, mseledtsov diff -r 2601fc0874be -r 9fe5d0d4e9c5 src/hotspot/share/jfr/leakprofiler/checkpoint/eventEmitter.cpp --- a/src/hotspot/share/jfr/leakprofiler/checkpoint/eventEmitter.cpp Fri Nov 22 19:23:30 2019 -0800 +++ b/src/hotspot/share/jfr/leakprofiler/checkpoint/eventEmitter.cpp Sun Nov 24 01:03:33 2019 +0100 @@ -128,10 +128,13 @@ const traceid object_id = edge_store->get_id(edge); assert(object_id != 0, "invariant"); + Tickspan object_age = Ticks(_start_time.value()) - sample->allocation_time(); + EventOldObjectSample e(UNTIMED); e.set_starttime(_start_time); e.set_endtime(_end_time); e.set_allocationTime(sample->allocation_time()); + e.set_objectAge(object_age); e.set_lastKnownHeapUsage(sample->heap_used_at_last_gc()); e.set_object(object_id); e.set_arrayElements(array_size(edge->pointee())); diff -r 2601fc0874be -r 9fe5d0d4e9c5 src/hotspot/share/jfr/metadata/metadata.xml --- a/src/hotspot/share/jfr/metadata/metadata.xml Fri Nov 22 19:23:30 2019 -0800 +++ b/src/hotspot/share/jfr/metadata/metadata.xml Sun Nov 24 01:03:33 2019 +0100 @@ -579,6 +579,7 @@ + diff -r 2601fc0874be -r 9fe5d0d4e9c5 src/hotspot/share/utilities/ticks.hpp --- a/src/hotspot/share/utilities/ticks.hpp Fri Nov 22 19:23:30 2019 -0800 +++ b/src/hotspot/share/utilities/ticks.hpp Sun Nov 24 01:03:33 2019 +0100 @@ -233,6 +233,7 @@ TimeInstant(jlong ticks) : Rep(ticks) {} friend class GranularTimer; friend class ObjectSample; + friend class EventEmitter; // GC unit tests friend class TimePartitionPhasesIteratorTest; friend class GCTimerTest; diff -r 2601fc0874be -r 9fe5d0d4e9c5 test/jdk/jdk/jfr/event/oldobject/TestObjectAge.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/jdk/jfr/event/oldobject/TestObjectAge.java Sun Nov 24 01:03:33 2019 +0100 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.jfr.event.oldobject; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.List; + +import jdk.jfr.Recording; +import jdk.jfr.consumer.RecordedEvent; +import jdk.jfr.internal.test.WhiteBox; +import jdk.test.lib.jfr.EventNames; +import jdk.test.lib.jfr.Events; + +/** + * @test + * @key jfr + * @requires vm.hasJFR + * @requires vm.gc == "null" + * @library /test/lib /test/jdk + * @modules jdk.jfr/jdk.jfr.internal.test + * @run main/othervm -XX:TLABSize=2k jdk.jfr.event.oldobject.TestObjectAge + */ +public class TestObjectAge { + + public final static List leak = new ArrayList<>(OldObjects.MIN_SIZE); + + public static void main(String[] args) throws Exception { + WhiteBox.setWriteAllObjectSamples(true); + + try (Recording recording = new Recording()) { + recording.enable(EventNames.OldObjectSample).withStackTrace().with("cutoff", "1 h"); + recording.start(); + + // Allocate array to trigger sampling code path for interpreter / c1 + for (int i = 0; i < OldObjects.MIN_SIZE; i++) { + leak.add(new Object[0]); + } + recording.stop(); + + List events = Events.fromRecording(recording); + // OK if we sometimes don't get an event + for (RecordedEvent event : events) { + Duration objectAge = event.getDuration("objectAge"); + // Sanity check + if (objectAge.isNegative() || objectAge.toMinutes() > 60) { + throw new Exception("Object age " + objectAge + " is not reasonable"); + } + } + } + } +}