Skip to content
This repository was archived by the owner on Aug 27, 2022. It is now read-only.
/ lanai Public archive

Commit 5d9c59f

Browse files
committedFeb 17, 2020
8238236: Add JFR class redefinition events
Reviewed-by: mgronlun
1 parent 74bee68 commit 5d9c59f

File tree

9 files changed

+129
-7
lines changed

9 files changed

+129
-7
lines changed
 

‎src/hotspot/share/jfr/metadata/metadata.xml

+18-1
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,22 @@
101101
<Field type="ClassLoader" name="definingClassLoader" label="Defining Class Loader" />
102102
</Event>
103103

104+
<Event name="ClassRedefinition" category="Java Virtual Machine, Class Loading" label="Class Redefinition" thread="false" stackTrace="false" startTime="false">
105+
<Field type="Class" name="redefinedClass" label="Redefined Class" />
106+
<Field type="int" name="classModificationCount" label="Class Modification Count" description="The number of times the class has changed"/>
107+
<Field type="ulong" name="redefinitionId" label="Class Redefinition Id" relation="ClassRedefinitionId"/>
108+
</Event>
109+
110+
<Event name="RedefineClasses" category="Java Virtual Machine, Class Loading" label="Redefine Classes" thread="true" stackTrace="true">
111+
<Field type="int" name="classCount" label="Class Count" />
112+
<Field type="ulong" name="redefinitionId" label="Class Redefinition Id" relation="ClassRedefinitionId" />
113+
</Event>
114+
115+
<Event name="RetransformClasses" category="Java Virtual Machine, Class Loading" label="Retransform Classes" thread="true" stackTrace="true">
116+
<Field type="int" name="classCount" label="Class Count"/>
117+
<Field type="ulong" name="redefinitionId" label="Class Redefinition Id" relation="ClassRedefinitionId" />
118+
</Event>
119+
104120
<Event name="ClassUnload" category="Java Virtual Machine, Class Loading" label="Class Unload" thread="true" startTime="false">
105121
<Field type="Class" name="unloadedClass" label="Unloaded Class" />
106122
<Field type="ClassLoader" name="definingClassLoader" label="Defining Class Loader" />
@@ -1236,7 +1252,8 @@
12361252
<Relation name="CompileId" />
12371253
<Relation name="SweepId"/>
12381254
<Relation name="FlushId"/>
1239-
1255+
<Relation name="ClassRedefinitionId"/>
1256+
12401257
<XmlType name="Package" parameterType="const PackageEntry*" fieldType="const PackageEntry*"/>
12411258
<XmlType name="Class" javaType="java.lang.Class" parameterType="const Klass*" fieldType="const Klass*"/>
12421259
<XmlType name="Module" parameterType="const ModuleEntry*" fieldType="const ModuleEntry*"/>

‎src/hotspot/share/prims/jvmtiEnv.cpp

+17-2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "classfile/vmSymbols.hpp"
3232
#include "interpreter/bytecodeStream.hpp"
3333
#include "interpreter/interpreter.hpp"
34+
#include "jfr/jfrEvents.hpp"
3435
#include "jvmtifiles/jvmtiEnv.hpp"
3536
#include "logging/log.hpp"
3637
#include "logging/logConfiguration.hpp"
@@ -446,9 +447,16 @@ JvmtiEnv::RetransformClasses(jint class_count, const jclass* classes) {
446447
}
447448
class_definitions[index].klass = jcls;
448449
}
450+
EventRetransformClasses event;
449451
VM_RedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_retransform);
450452
VMThread::execute(&op);
451-
return (op.check_error());
453+
jvmtiError error = op.check_error();
454+
if (error == JVMTI_ERROR_NONE) {
455+
event.set_classCount(class_count);
456+
event.set_redefinitionId(op.id());
457+
event.commit();
458+
}
459+
return error;
452460
} /* end RetransformClasses */
453461

454462

@@ -457,9 +465,16 @@ JvmtiEnv::RetransformClasses(jint class_count, const jclass* classes) {
457465
jvmtiError
458466
JvmtiEnv::RedefineClasses(jint class_count, const jvmtiClassDefinition* class_definitions) {
459467
//TODO: add locking
468+
EventRedefineClasses event;
460469
VM_RedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine);
461470
VMThread::execute(&op);
462-
return (op.check_error());
471+
jvmtiError error = op.check_error();
472+
if (error == JVMTI_ERROR_NONE) {
473+
event.set_classCount(class_count);
474+
event.set_redefinitionId(op.id());
475+
event.commit();
476+
}
477+
return error;
463478
} /* end RedefineClasses */
464479

465480

‎src/hotspot/share/prims/jvmtiRedefineClasses.cpp

+25-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -35,6 +35,7 @@
3535
#include "compiler/compileBroker.hpp"
3636
#include "interpreter/oopMapCache.hpp"
3737
#include "interpreter/rewriter.hpp"
38+
#include "jfr/jfrEvents.hpp"
3839
#include "logging/logStream.hpp"
3940
#include "memory/metadataFactory.hpp"
4041
#include "memory/metaspaceShared.hpp"
@@ -51,6 +52,7 @@
5152
#include "prims/jvmtiThreadState.inline.hpp"
5253
#include "prims/resolvedMethodTable.hpp"
5354
#include "prims/methodComparator.hpp"
55+
#include "runtime/atomic.hpp"
5456
#include "runtime/deoptimization.hpp"
5557
#include "runtime/handles.inline.hpp"
5658
#include "runtime/jniHandles.inline.hpp"
@@ -70,7 +72,7 @@ int VM_RedefineClasses::_deleted_methods_length = 0;
7072
int VM_RedefineClasses::_added_methods_length = 0;
7173
bool VM_RedefineClasses::_has_redefined_Object = false;
7274
bool VM_RedefineClasses::_has_null_class_loader = false;
73-
75+
u8 VM_RedefineClasses::_id_counter = 0;
7476

7577
VM_RedefineClasses::VM_RedefineClasses(jint class_count,
7678
const jvmtiClassDefinition *class_defs,
@@ -83,6 +85,7 @@ VM_RedefineClasses::VM_RedefineClasses(jint class_count,
8385
_the_class = NULL;
8486
_has_redefined_Object = false;
8587
_has_null_class_loader = false;
88+
_id = next_id();
8689
}
8790

8891
static inline InstanceKlass* get_ik(jclass def) {
@@ -4294,6 +4297,15 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass,
42944297
}
42954298

42964299
increment_class_counter((InstanceKlass *)the_class, THREAD);
4300+
4301+
if (EventClassRedefinition::is_enabled()) {
4302+
EventClassRedefinition event;
4303+
event.set_classModificationCount(java_lang_Class::classRedefinedCount(the_class->java_mirror()));
4304+
event.set_redefinedClass(the_class);
4305+
event.set_redefinitionId(_id);
4306+
event.commit();
4307+
}
4308+
42974309
{
42984310
ResourceMark rm(THREAD);
42994311
// increment the classRedefinedCount field in the_class and in any
@@ -4307,6 +4319,7 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass,
43074319

43084320
}
43094321
_timer_rsc_phase2.stop();
4322+
43104323
} // end redefine_single_class()
43114324

43124325

@@ -4393,6 +4406,16 @@ void VM_RedefineClasses::CheckClass::do_klass(Klass* k) {
43934406
}
43944407
}
43954408

4409+
u8 VM_RedefineClasses::next_id() {
4410+
while (true) {
4411+
u8 id = _id_counter;
4412+
u8 next_id = id + 1;
4413+
u8 result = Atomic::cmpxchg(&_id_counter, id, next_id);
4414+
if (result == id) {
4415+
return next_id;
4416+
}
4417+
}
4418+
}
43964419

43974420
void VM_RedefineClasses::dump_methods() {
43984421
int j;

‎src/hotspot/share/prims/jvmtiRedefineClasses.hpp

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -351,6 +351,9 @@ class VM_RedefineClasses: public VM_Operation {
351351
static bool _has_redefined_Object;
352352
static bool _has_null_class_loader;
353353

354+
// Used by JFR to group class redefininition events together.
355+
static u8 _id_counter;
356+
354357
// The instance fields are used to pass information from
355358
// doit_prologue() to doit() and doit_epilogue().
356359
Klass* _the_class;
@@ -388,6 +391,9 @@ class VM_RedefineClasses: public VM_Operation {
388391
elapsedTimer _timer_rsc_phase2;
389392
elapsedTimer _timer_vm_op_prologue;
390393

394+
// Redefinition id used by JFR
395+
u8 _id;
396+
391397
// These routines are roughly in call order unless otherwise noted.
392398

393399
// Load the caller's new class definition(s) into _scratch_classes.
@@ -503,6 +509,8 @@ class VM_RedefineClasses: public VM_Operation {
503509
void lock_classes();
504510
void unlock_classes();
505511

512+
u8 next_id();
513+
506514
static void dump_methods();
507515

508516
// Check that there are no old or obsolete methods
@@ -535,6 +543,7 @@ class VM_RedefineClasses: public VM_Operation {
535543

536544
bool allow_nested_vm_operations() const { return true; }
537545
jvmtiError check_error() { return _res; }
546+
u8 id() { return _id; }
538547

539548
// Modifiable test must be shared between IsModifiableClass query
540549
// and redefine implementation

‎src/jdk.jfr/share/conf/jfr/default.jfc

+16
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,22 @@
124124
<setting name="stackTrace">true</setting>
125125
</event>
126126

127+
<event name="jdk.RedefineClasses">
128+
<setting name="enabled">true</setting>
129+
<setting name="stackTrace">true</setting>
130+
<setting name="threshold">0 ms</setting>
131+
</event>
132+
133+
<event name="jdk.RetransformClasses">
134+
<setting name="enabled">true</setting>
135+
<setting name="stackTrace">true</setting>
136+
<setting name="threshold">0 ms</setting>
137+
</event>
138+
139+
<event name="jdk.ClassRedefinition">
140+
<setting name="enabled" control="class-loading-enabled">true</setting>
141+
</event>
142+
127143
<event name="jdk.ClassUnload">
128144
<setting name="enabled" control="class-loading-enabled">false</setting>
129145
</event>

‎src/jdk.jfr/share/conf/jfr/profile.jfc

+16
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,22 @@
124124
<setting name="stackTrace">true</setting>
125125
</event>
126126

127+
<event name="jdk.RedefineClasses">
128+
<setting name="enabled">true</setting>
129+
<setting name="stackTrace">true</setting>
130+
<setting name="threshold">0 ms</setting>
131+
</event>
132+
133+
<event name="jdk.RetransformClasses">
134+
<setting name="enabled">true</setting>
135+
<setting name="stackTrace">true</setting>
136+
<setting name="threshold">0 ms</setting>
137+
</event>
138+
139+
<event name="jdk.ClassRedefinition">
140+
<setting name="enabled" control="class-loading-enabled">true</setting>
141+
</event>
142+
127143
<event name="jdk.ClassUnload">
128144
<setting name="enabled" control="class-loading-enabled">false</setting>
129145
</event>

‎test/lib/jdk/test/lib/jfr/EventNames.java

+4
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ public class EventNames {
8787
public final static String PlaceholderTableStatistics = PREFIX + "PlaceholderTableStatistics";
8888
public final static String LoaderConstraintsTableStatistics = PREFIX + "LoaderConstraintsTableStatistics";
8989
public final static String ProtectionDomainCacheTableStatistics = PREFIX + "ProtectionDomainCacheTableStatistics";
90+
public static final String RedefineClasses = PREFIX + "RedefineClasses";
91+
public static final String RetransformClasses = PREFIX + "RetransformClasses";
92+
public static final String ClassRedefinition = PREFIX + "ClassRedefinition";
93+
9094
// This event is hard to test
9195
public final static String ReservedStackActivation = PREFIX + "ReservedStackActivation";
9296

‎test/lib/jdk/test/lib/jfr/Events.java

+21-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -48,7 +48,10 @@
4848
import jdk.test.lib.Asserts;
4949
import jdk.jfr.consumer.RecordedClass;
5050
import jdk.jfr.consumer.RecordedEvent;
51+
import jdk.jfr.consumer.RecordedFrame;
52+
import jdk.jfr.consumer.RecordedMethod;
5153
import jdk.jfr.consumer.RecordedObject;
54+
import jdk.jfr.consumer.RecordedStackTrace;
5255
import jdk.jfr.consumer.RecordedThread;
5356
import jdk.jfr.consumer.RecordedThreadGroup;
5457

@@ -363,4 +366,21 @@ private static boolean containsEvent(List<RecordedEvent> events, String name) {
363366
}
364367
return false;
365368
}
369+
370+
public static void assertFrame(RecordedEvent event, Class<?> expectedClass, String expectedMethodName) {
371+
RecordedStackTrace stackTrace = event.getStackTrace();
372+
Asserts.assertNotNull(stackTrace, "Missing stack trace");
373+
for (RecordedFrame frame : stackTrace.getFrames()) {
374+
if (frame.isJavaFrame()) {
375+
RecordedMethod method = frame.getMethod();
376+
RecordedClass type = method.getType();
377+
if (expectedClass.getName().equals(type.getName())) {
378+
if (expectedMethodName.equals(method.getName())) {
379+
return;
380+
}
381+
}
382+
}
383+
}
384+
Asserts.fail("Expected " + expectedClass.getName() + "::"+ expectedMethodName + " in stack trace");
385+
}
366386
}

‎test/lib/jdk/test/lib/util/JavaAgentBuilder.java

+2
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ public static void build(String agentClass, String agentJar) throws IOException
7373
Manifest mf = new Manifest();
7474
Attributes attrs = mf.getMainAttributes();
7575
attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0");
76+
attrs.putValue("Can-Redefine-Classes", "true");
77+
attrs.putValue("Can-Retransform-Classes", "true");
7678
attrs.putValue("Premain-Class", agentClass);
7779
attrs.putValue("Agent-Class", agentClass);
7880

0 commit comments

Comments
 (0)
This repository has been archived.