Skip to content

Commit 971e6dc

Browse files
Kerem Katshipilev
authored andcommitted
8212155: Race condition when posting dynamic_code_generated event leads to JVM crash
Reviewed-by: shade Backport-of: 64ec8b3
1 parent 7ff53b5 commit 971e6dc

File tree

3 files changed

+124
-7
lines changed

3 files changed

+124
-7
lines changed

src/hotspot/share/prims/jvmtiExport.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2284,13 +2284,17 @@ void JvmtiExport::post_dynamic_code_generated_while_holding_locks(const char* na
22842284
address code_begin, address code_end)
22852285
{
22862286
// register the stub with the current dynamic code event collector
2287-
JvmtiThreadState* state = JvmtiThreadState::state_for(JavaThread::current());
2288-
// state can only be NULL if the current thread is exiting which
2289-
// should not happen since we're trying to post an event
2290-
guarantee(state != NULL, "attempt to register stub via an exiting thread");
2291-
JvmtiDynamicCodeEventCollector* collector = state->get_dynamic_code_event_collector();
2292-
guarantee(collector != NULL, "attempt to register stub without event collector");
2293-
collector->register_stub(name, code_begin, code_end);
2287+
// Cannot take safepoint here so do not use state_for to get
2288+
// jvmti thread state.
2289+
// The collector and/or state might be NULL if JvmtiDynamicCodeEventCollector
2290+
// has been initialized while JVMTI_EVENT_DYNAMIC_CODE_GENERATED was disabled.
2291+
JvmtiThreadState* state = JavaThread::current()->jvmti_thread_state();
2292+
if (state != NULL) {
2293+
JvmtiDynamicCodeEventCollector *collector = state->get_dynamic_code_event_collector();
2294+
if (collector != NULL) {
2295+
collector->register_stub(name, code_begin, code_end);
2296+
}
2297+
}
22942298
}
22952299

22962300
// Collect all the vm internally allocated objects which are visible to java world
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
/*
25+
* @test
26+
* @bug 8212155
27+
* @summary Test concurrent enabling and posting of DynamicCodeGenerated events.
28+
* @library /test/lib
29+
* @run main/othervm/native -agentlib:DynamicCodeGenerated DynamicCodeGeneratedTest
30+
*/
31+
32+
import java.lang.ref.Reference;
33+
34+
public class DynamicCodeGeneratedTest {
35+
static {
36+
System.loadLibrary("DynamicCodeGenerated");
37+
}
38+
public static native void changeEventNotificationMode();
39+
40+
public static void main(String[] args) {
41+
// Try to enable DynamicCodeGenerated event while it is posted
42+
// using JvmtiDynamicCodeEventCollector from VtableStubs::find_stub
43+
Thread t = new Thread(() -> {
44+
changeEventNotificationMode();
45+
});
46+
t.setDaemon(true);
47+
t.start();
48+
49+
for (int i = 0; i < 2000; i++) {
50+
new Thread(() -> {
51+
String result = "string" + System.currentTimeMillis();
52+
Reference.reachabilityFence(result);
53+
}).start();
54+
}
55+
}
56+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
#include <string.h>
25+
#include <jvmti.h>
26+
27+
static jvmtiEnv* jvmti = NULL;
28+
29+
#ifdef __cplusplus
30+
extern "C" {
31+
#endif
32+
33+
JNIEXPORT
34+
void JNICALL Java_DynamicCodeGeneratedTest_changeEventNotificationMode(JNIEnv* jni, jclass cls) {
35+
while (true) {
36+
jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_DYNAMIC_CODE_GENERATED, NULL);
37+
jvmti->SetEventNotificationMode(JVMTI_DISABLE, JVMTI_EVENT_DYNAMIC_CODE_GENERATED, NULL);
38+
}
39+
}
40+
41+
#ifdef __cplusplus
42+
}
43+
#endif
44+
45+
void JNICALL DynamicCodeGenerated(jvmtiEnv* jvmti, const char* name, const void* address, jint length) {
46+
47+
}
48+
49+
jint Agent_OnLoad(JavaVM* vm, char* options, void* reserved) {
50+
vm->GetEnv((void**)&jvmti, JVMTI_VERSION_1_0);
51+
jvmtiEventCallbacks callbacks;
52+
memset(&callbacks, 0, sizeof(callbacks));
53+
callbacks.DynamicCodeGenerated = DynamicCodeGenerated;
54+
jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks));
55+
56+
return 0;
57+
}

0 commit comments

Comments
 (0)