Skip to content

Commit 705bd6f

Browse files
committed
8367902: Allocation after Universe::before_exit() in the VM shutdown sequence
Reviewed-by: ayang, stefank, iwalulya, aboldtch, sspitsyn
1 parent 78db38f commit 705bd6f

File tree

3 files changed

+152
-10
lines changed

3 files changed

+152
-10
lines changed

src/hotspot/share/runtime/java.cpp

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,18 @@ void before_exit(JavaThread* thread, bool halt) {
476476

477477
NativeHeapTrimmer::cleanup();
478478

479-
// Run before exit and then stop concurrent GC threads
479+
if (JvmtiExport::should_post_thread_life()) {
480+
JvmtiExport::post_thread_end(thread);
481+
}
482+
483+
// Always call even when there are not JVMTI environments yet, since environments
484+
// may be attached late and JVMTI must track phases of VM execution.
485+
JvmtiExport::post_vm_death();
486+
JvmtiAgentList::unload_agents();
487+
488+
// No user code can be executed in the current thread after this point.
489+
490+
// Run before exit and then stop concurrent GC threads.
480491
Universe::before_exit();
481492

482493
if (PrintBytecodeHistogram) {
@@ -492,15 +503,6 @@ void before_exit(JavaThread* thread, bool halt) {
492503
}
493504
#endif
494505

495-
if (JvmtiExport::should_post_thread_life()) {
496-
JvmtiExport::post_thread_end(thread);
497-
}
498-
499-
// Always call even when there are not JVMTI environments yet, since environments
500-
// may be attached late and JVMTI must track phases of VM execution
501-
JvmtiExport::post_vm_death();
502-
JvmtiAgentList::unload_agents();
503-
504506
// Terminate the signal thread
505507
// Note: we don't wait until it actually dies.
506508
os::terminate_signal_thread();
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
* Copyright (c) 2025, 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+
* @summary Test verifies that VM still can execute java code, allocate
27+
* memory, and call GC in the VMDeath event callback.
28+
*
29+
* @bug 8367902
30+
* @requires vm.jvmti
31+
* @library /test/lib
32+
* @build jdk.test.whitebox.WhiteBox
33+
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
34+
* @run main/othervm/native TestAllocatingInVMDeath
35+
*/
36+
import java.time.LocalDateTime;
37+
import java.time.format.DateTimeFormatter;
38+
39+
import jdk.test.lib.Asserts;
40+
import jdk.test.lib.process.OutputAnalyzer;
41+
import jdk.test.lib.process.ProcessTools;
42+
import jdk.test.whitebox.WhiteBox;
43+
44+
public class TestAllocatingInVMDeath {
45+
public static String UPCALL_MARKER = "Hello from upCall. ";
46+
47+
public static void main(String[] args) throws Exception {
48+
ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder(
49+
"-agentlib:TestAllocatingInVMDeath",
50+
"--enable-native-access=ALL-UNNAMED",
51+
"-Xbootclasspath/a:.",
52+
"-XX:+UnlockDiagnosticVMOptions",
53+
"-XX:+WhiteBoxAPI",
54+
"DoWork");
55+
56+
OutputAnalyzer oa = new OutputAnalyzer(pb.start());
57+
String output = oa.getOutput();
58+
System.err.println("DoWork output:");
59+
System.err.println(output);
60+
Asserts.assertTrue(oa.getExitValue() == 0);
61+
Asserts.assertTrue(output.contains(UPCALL_MARKER));
62+
}
63+
}
64+
65+
class DoWork {
66+
static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
67+
68+
// This method is called from VMDeath event callback.
69+
static void upCall() {
70+
// Do some work including memory allocation, so it can't be optimized by compiler.
71+
LocalDateTime now = LocalDateTime.now();
72+
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
73+
String result = TestAllocatingInVMDeath.UPCALL_MARKER + now.format(formatter);
74+
WHITE_BOX.fullGC();
75+
System.out.println(result);
76+
}
77+
78+
public static void main(String argv[]) throws Exception {
79+
System.out.println("Hello from DoWork main().");
80+
}
81+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Copyright (c) 2025, 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 "jvmti.h"
25+
#include "jni.h"
26+
#include "jvmti_common.hpp"
27+
28+
static void JNICALL
29+
cbVMDeath(jvmtiEnv* jvmti, JNIEnv* jni) {
30+
jclass clz = jni->FindClass("DoWork");
31+
if (clz == nullptr) {
32+
fatal(jni, "Can't find DoWork class.");
33+
return;
34+
}
35+
jmethodID mid = jni->GetStaticMethodID(clz, "upCall", "()V");
36+
if (mid == nullptr) {
37+
fatal(jni, "Can't find upCall method.");
38+
}
39+
jni->CallStaticObjectMethod(clz, mid);
40+
}
41+
42+
JNIEXPORT jint JNICALL
43+
Agent_OnLoad(JavaVM *vm, char *options, void *reserved) {
44+
jvmtiEnv *jvmti = nullptr;
45+
jint res = vm->GetEnv((void **) &jvmti, JVMTI_VERSION_21);
46+
if (res != JNI_OK) {
47+
return JNI_ERR;
48+
}
49+
jvmtiError err = JVMTI_ERROR_NONE;
50+
51+
jvmtiEventCallbacks callbacks;
52+
(void) memset(&callbacks, 0, sizeof (callbacks));
53+
callbacks.VMDeath = &cbVMDeath;
54+
err = jvmti->SetEventCallbacks(&callbacks, (int) sizeof (jvmtiEventCallbacks));
55+
check_jvmti_error(err, "SetEventCallbacks");
56+
err = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH, nullptr);
57+
check_jvmti_error(err, "SetEventNotificationMode");
58+
return JNI_OK;
59+
}

0 commit comments

Comments
 (0)