Skip to content

Commit 4a449ef

Browse files
committed
Prevent contended monitor enters at CRIU single thread mode
objectMonitorEnterNonBlocking() returns J9_OBJECT_MONITOR_CRIU_SINGLE_THREAD_MODE_THROW instead of J9_OBJECT_MONITOR_BLOCKING; Updated the callers to handle this additional return value J9_OBJECT_MONITOR_CRIU_SINGLE_THREAD_MODE_THROW; Add tests. Signed-off-by: Jason Feng <fengj@ca.ibm.com>
1 parent f9c5836 commit 4a449ef

23 files changed

+524
-111
lines changed

runtime/codert_vm/cnathelp.cpp

+24-5
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,16 @@ setNativeOutOfMemoryErrorFromJIT(J9VMThread *currentThread, U_32 moduleName, U_3
417417
return J9_JITHELPER_ACTION_THROW;
418418
}
419419

420+
#if defined(J9VM_OPT_CRIU_SUPPORT)
421+
static VMINLINE void*
422+
setCRIUSingleThreadModeExceptionFromJIT(J9VMThread *currentThread, U_32 moduleName, U_32 messageNumber)
423+
{
424+
TIDY_BEFORE_THROW();
425+
currentThread->javaVM->internalVMFunctions->setCRIUSingleThreadModeJVMCRIUException(currentThread, moduleName, messageNumber);
426+
return J9_JITHELPER_ACTION_THROW;
427+
}
428+
#endif /* defined(J9VM_OPT_CRIU_SUPPORT) */
429+
420430
static VMINLINE void*
421431
setHeapOutOfMemoryErrorFromJIT(J9VMThread *currentThread)
422432
{
@@ -1725,8 +1735,9 @@ slow_jitMonitorEnterImpl(J9VMThread *currentThread, bool forMethod)
17251735
resolveFrame->specialFrameFlags = (resolveFrame->specialFrameFlags & ~J9_STACK_FLAGS_JIT_FRAME_SUB_TYPE_MASK) | J9_STACK_FLAGS_JIT_FAILED_METHOD_MONITOR_ENTER_RESOLVE;
17261736
}
17271737
}
1738+
switch (monstatus) {
17281739
#if JAVA_SPEC_VERSION >= 16
1729-
if (J9_OBJECT_MONITOR_VALUE_TYPE_IMSE == monstatus) {
1740+
case J9_OBJECT_MONITOR_VALUE_TYPE_IMSE: {
17301741
j9object_t syncObject = (j9object_t)currentThread->floatTemp2;
17311742
J9Class* badClass = J9OBJECT_CLAZZ(currentThread, syncObject);
17321743
J9UTF8 *className = J9ROMCLASS_CLASSNAME(badClass->romClass);
@@ -1740,16 +1751,24 @@ slow_jitMonitorEnterImpl(J9VMThread *currentThread, bool forMethod)
17401751
{
17411752
Assert_CodertVM_true(J9_ARE_ALL_BITS_SET(currentThread->javaVM->extendedRuntimeFlags2, J9_EXTENDED_RUNTIME2_VALUE_BASED_EXCEPTION));
17421753
currentThread->javaVM->internalVMFunctions->setCurrentExceptionNLSWithArgs(currentThread, J9NLS_VM_ERROR_BYTECODE_OBJECTREF_CANNOT_BE_VALUE_BASED,
1743-
J9VMCONSTANTPOOL_JAVALANGVIRTUALMACHINEERROR, J9UTF8_LENGTH(className), J9UTF8_DATA(className));
1754+
J9VMCONSTANTPOOL_JAVALANGVIRTUALMACHINEERROR, J9UTF8_LENGTH(className), J9UTF8_DATA(className));
17441755
}
17451756
addr = J9_JITHELPER_ACTION_THROW;
1746-
goto done;
1757+
break;
17471758
}
17481759
#endif /* JAVA_SPEC_VERSION >= 16 */
1749-
if (J9_OBJECT_MONITOR_OOM == monstatus) {
1760+
#if defined(J9VM_OPT_CRIU_SUPPORT)
1761+
case J9_OBJECT_MONITOR_CRIU_SINGLE_THREAD_MODE_THROW:
1762+
addr = setCRIUSingleThreadModeExceptionFromJIT(currentThread, J9NLS_VM_CRIU_SINGLETHREADMODE_JVMCRIUEXCEPTION);
1763+
break;
1764+
#endif /* defined(J9VM_OPT_CRIU_SUPPORT) */
1765+
case J9_OBJECT_MONITOR_OOM:
17501766
addr = setNativeOutOfMemoryErrorFromJIT(currentThread, J9NLS_VM_FAILED_TO_ALLOCATE_MONITOR);
1751-
goto done;
1767+
break;
1768+
default:
1769+
Assert_CodertVM_unreachable();
17521770
}
1771+
goto done;
17531772
} else {
17541773
currentThread->javaVM->internalVMFunctions->objectMonitorEnterBlocking(currentThread);
17551774
/* Do not check asyncs for synchronized block (non-method) entry, since we now have the monitor,

runtime/jcl/common/sun_misc_Unsafe.cpp

+9-2
Original file line numberDiff line numberDiff line change
@@ -405,9 +405,16 @@ Java_sun_misc_Unsafe_monitorEnter(JNIEnv *env, jobject receiver, jobject obj)
405405
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGNULLPOINTEREXCEPTION, NULL);
406406
} else {
407407
UDATA monresult = vmFuncs->objectMonitorEnter(currentThread, J9_JNI_UNWRAP_REFERENCE(obj));
408-
if (0 == monresult) {
408+
if (J9_OBJECT_MONITOR_ENTER_FAILED(monresult)) {
409+
#if defined(J9VM_OPT_CRIU_SUPPORT)
410+
if (J9_OBJECT_MONITOR_CRIU_SINGLE_THREAD_MODE_THROW == monresult) {
411+
vmFuncs->setCRIUSingleThreadModeJVMCRIUException(currentThread, 0, 0);
412+
} else
413+
#endif /* defined(J9VM_OPT_CRIU_SUPPORT) */
414+
if (J9_OBJECT_MONITOR_OOM == monresult) {
409415
oom:
410-
vmFuncs->setNativeOutOfMemoryError(currentThread, 0, 0);
416+
vmFuncs->setNativeOutOfMemoryError(currentThread, 0, 0);
417+
}
411418
} else if (J9_UNEXPECTED(!VM_ObjectMonitor::recordJNIMonitorEnter(currentThread, (j9object_t)monresult))) {
412419
vmFuncs->objectMonitorExit(currentThread, (j9object_t)monresult);
413420
goto oom;

runtime/jvmti/jvmtiThreadGroup.c

+20-4
Original file line numberDiff line numberDiff line change
@@ -183,8 +183,16 @@ jvmtiGetThreadGroupChildren(jvmtiEnv* env,
183183
childrenGroupsLock = (j9object_t)vmFuncs->objectMonitorEnter(currentThread, childrenGroupsLock);
184184
/* The threadGroupObject has to be reobtained as it might have been GC'ed while waiting for the lock */
185185
threadGroupObject = *((j9object_t*)group);
186-
if (J9_OBJECT_MONITOR_ENTER_FAILED((UDATA)childrenGroupsLock)) {
187-
rc = JVMTI_ERROR_OUT_OF_MEMORY;
186+
if (J9_OBJECT_MONITOR_ENTER_FAILED(childrenGroupsLock)) {
187+
#if defined(J9VM_OPT_CRIU_SUPPORT)
188+
if (J9_OBJECT_MONITOR_CRIU_SINGLE_THREAD_MODE_THROW == (UDATA)childrenGroupsLock) {
189+
vmFuncs->setCRIUSingleThreadModeJVMCRIUException(currentThread, 0, 0);
190+
rc = JVMTI_ERROR_THREAD_SUSPENDED;
191+
} else
192+
#endif /* defined(J9VM_OPT_CRIU_SUPPORT) */
193+
if (J9_OBJECT_MONITOR_OOM == (UDATA)childrenGroupsLock) {
194+
rc = JVMTI_ERROR_OUT_OF_MEMORY;
195+
}
188196
goto done;
189197
}
190198

@@ -211,8 +219,16 @@ jvmtiGetThreadGroupChildren(jvmtiEnv* env,
211219
childrenThreadsLock = (j9object_t)vmFuncs->objectMonitorEnter(currentThread, childrenThreadsLock);
212220
/* The threadGroupObject has to be reobtained as it might have been GC'ed while waiting for the lock */
213221
threadGroupObject = *((j9object_t*)group);
214-
if (J9_OBJECT_MONITOR_ENTER_FAILED((UDATA)childrenThreadsLock)) {
215-
rc = JVMTI_ERROR_OUT_OF_MEMORY;
222+
if (J9_OBJECT_MONITOR_ENTER_FAILED(childrenThreadsLock)) {
223+
#if defined(J9VM_OPT_CRIU_SUPPORT)
224+
if (J9_OBJECT_MONITOR_CRIU_SINGLE_THREAD_MODE_THROW == (UDATA)childrenThreadsLock) {
225+
vmFuncs->setCRIUSingleThreadModeJVMCRIUException(currentThread, 0, 0);
226+
rc = JVMTI_ERROR_THREAD_SUSPENDED;
227+
} else
228+
#endif /* defined(J9VM_OPT_CRIU_SUPPORT) */
229+
if (J9_OBJECT_MONITOR_OOM == (UDATA)childrenThreadsLock) {
230+
rc = JVMTI_ERROR_OUT_OF_MEMORY;
231+
}
216232
j9mem_free_memory(groups);
217233
goto done;
218234
}

runtime/nls/j9vm/j9vm.nls

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#
2-
# Copyright (c) 2000, 2021 IBM Corp. and others
2+
# Copyright (c) 2000, 2022 IBM Corp. and others
33
#
44
# This program and the accompanying materials are made available under
55
# the terms of the Eclipse Public License 2.0 which accompanies this
@@ -2097,3 +2097,11 @@ J9NLS_ENSUREHASHED_CONFIG_OUT_OF_MEM.explanation=There was a failure to allocate
20972097
J9NLS_ENSUREHASHED_CONFIG_OUT_OF_MEM.system_action=The JVM prints this message and terminates.
20982098
J9NLS_ENSUREHASHED_CONFIG_OUT_OF_MEM.user_response=Check the system memory configuration.
20992099
# END NON-TRANSLATABLE
2100+
2101+
# JVMCRIUException is thrown to indicate that blocking operation is not allowed in CRIU single thread mode
2102+
J9NLS_VM_CRIU_SINGLETHREADMODE_JVMCRIUEXCEPTION=Blocking operation is not allowed in CRIU single thread mode.
2103+
# START NON-TRANSLATABLE
2104+
J9NLS_VM_CRIU_SINGLETHREADMODE_JVMCRIUEXCEPTION.explanation=Blocking operation is not allowed in CRIU single thread mode.
2105+
J9NLS_VM_CRIU_SINGLETHREADMODE_JVMCRIUEXCEPTION.system_action=The JVM will throw a JVMCRIUException.
2106+
J9NLS_VM_CRIU_SINGLETHREADMODE_JVMCRIUEXCEPTION.user_response=View CRIU documentation to determine how to resolve the exception.
2107+
# END NON-TRANSLATABLE

runtime/oti/j9nonbuilder.h

+9-10
Original file line numberDiff line numberDiff line change
@@ -4867,6 +4867,7 @@ typedef struct J9InternalVMFunctions {
48674867
BOOLEAN (*runInternalJVMCheckpointHooks)(struct J9VMThread *currentThread);
48684868
BOOLEAN (*runInternalJVMRestoreHooks)(struct J9VMThread *currentThread);
48694869
BOOLEAN (*runDelayedLockRelatedOperations)(struct J9VMThread *currentThread);
4870+
void (*setCRIUSingleThreadModeJVMCRIUException)(struct J9VMThread *vmThread, U_32 moduleName, U_32 messageNumber);
48704871
#endif /* defined(J9VM_OPT_CRIU_SUPPORT) */
48714872
j9object_t (*getClassNameString)(struct J9VMThread *currentThread, j9object_t classObject, jboolean internAndAssign);
48724873
j9object_t* (*getDefaultValueSlotAddress)(struct J9Class *clazz);
@@ -5692,18 +5693,16 @@ typedef struct J9JavaVM {
56925693
/* objectMonitorEnterNonBlocking return codes */
56935694
#define J9_OBJECT_MONITOR_OOM 0
56945695
#define J9_OBJECT_MONITOR_VALUE_TYPE_IMSE 1
5695-
/*
5696-
* Currently, not needed but reserving it for future use
5697-
*
5698-
* #define J9_OBJECT_MONITOR_PRIMITIVE_WRAPPER_IMSE 2
5699-
*/
5696+
#if defined(J9VM_OPT_CRIU_SUPPORT)
5697+
#define J9_OBJECT_MONITOR_CRIU_SINGLE_THREAD_MODE_THROW 2
5698+
#endif /* defined(J9VM_OPT_CRIU_SUPPORT) */
57005699
#define J9_OBJECT_MONITOR_BLOCKING 3
57015700

5702-
#if JAVA_SPEC_VERSION >= 16
5703-
#define J9_OBJECT_MONITOR_ENTER_FAILED(rc) ((rc) < J9_OBJECT_MONITOR_BLOCKING)
5704-
#else /* JAVA_SPEC_VERSION >= 16 */
5705-
#define J9_OBJECT_MONITOR_ENTER_FAILED(rc) ((rc) == J9_OBJECT_MONITOR_OOM)
5706-
#endif /* JAVA_SPEC_VERSION >= 16 */
5701+
#if (JAVA_SPEC_VERSION >= 16) || defined(J9VM_OPT_CRIU_SUPPORT)
5702+
#define J9_OBJECT_MONITOR_ENTER_FAILED(rc) ((UDATA)(rc) < J9_OBJECT_MONITOR_BLOCKING)
5703+
#else /* (JAVA_SPEC_VERSION >= 16) || defined(J9VM_OPT_CRIU_SUPPORT) */
5704+
#define J9_OBJECT_MONITOR_ENTER_FAILED(rc) ((UDATA)(rc) == J9_OBJECT_MONITOR_OOM)
5705+
#endif /* (JAVA_SPEC_VERSION >= 16) || defined(J9VM_OPT_CRIU_SUPPORT) */
57075706
#define J9JAVAVM_REFERENCE_SIZE(vm) (J9JAVAVM_COMPRESS_OBJECT_REFERENCES(vm) ? sizeof(U_32) : sizeof(UDATA))
57085707
#define J9JAVAVM_OBJECT_HEADER_SIZE(vm) (J9JAVAVM_COMPRESS_OBJECT_REFERENCES(vm) ? sizeof(J9ObjectCompressed) : sizeof(J9ObjectFull))
57095708
#define J9JAVAVM_CONTIGUOUS_HEADER_SIZE(vm) (J9JAVAVM_COMPRESS_OBJECT_REFERENCES(vm) ? sizeof(J9IndexableObjectContiguousCompressed) : sizeof(J9IndexableObjectContiguousFull))

runtime/oti/vm_api.h

+13
Original file line numberDiff line numberDiff line change
@@ -968,6 +968,19 @@ setClassLoadingConstraintSignatureError(J9VMThread *currentThread, J9ClassLoader
968968
void
969969
setClassLoadingConstraintOverrideError(J9VMThread *currentThread, J9UTF8 *newClassNameUTF, J9ClassLoader *loader1, J9UTF8 *class1NameUTF, J9ClassLoader *loader2, J9UTF8 *class2NameUTF, J9UTF8 *exceptionClassNameUTF, U_8 *methodName, UDATA methodNameLength, U_8 *signature, UDATA signatureLength);
970970

971+
#if defined(J9VM_OPT_CRIU_SUPPORT)
972+
/**
973+
* @brief Set JVMCRIUException to indicate that current operation is not allowed in CRIU single thread mode.
974+
* @param vmThread[in] the current J9VMThread
975+
* @param moduleName[in] the NLS module
976+
* @param messageNumber[in] the NLS message
977+
*
978+
* @return void
979+
*/
980+
void
981+
setCRIUSingleThreadModeJVMCRIUException(J9VMThread *vmThread, U_32 moduleName, U_32 messageNumber);
982+
#endif /* defined(J9VM_OPT_CRIU_SUPPORT) */
983+
971984
/* ---------------- extendedMessageNPE.cpp ---------------- */
972985

973986
/**

runtime/oti/vmconstantpool.xml

+3
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,9 @@ SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-excepti
151151

152152
<classref name="jdk/internal/vm/Continuation" versions="19-"/>
153153

154+
<classref name="org/eclipse/openj9/criu/JVMCheckpointException" flags="opt_criuSupport"/>
155+
<classref name="org/eclipse/openj9/criu/RestoreException" flags="opt_criuSupport"/>
156+
154157
<!--
155158
NOTE: the resolution code in jclcinit.c only looks at the J9ROMClassRef->runtimeFlags to determine
156159
whether or not to attempt the class load. The flags sepcified on the fields are ignored.

runtime/vm/BytecodeAction.hpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2001, 2020 IBM Corp. and others
2+
* Copyright (c) 2001, 2022 IBM Corp. and others
33
*
44
* This program and the accompanying materials are made available under
55
* the terms of the Eclipse Public License 2.0 which accompanies this
@@ -57,6 +57,9 @@ typedef enum {
5757
#if JAVA_SPEC_VERSION >= 16
5858
THROW_VALUE_TYPE_ILLEGAL_MONITOR_STATE,
5959
#endif /* JAVA_SPEC_VERSION >= 16 */
60+
#if defined(J9VM_OPT_CRIU_SUPPORT)
61+
THROW_CRIU_SINGLE_THREAD_MODE,
62+
#endif /* defined(J9VM_OPT_CRIU_SUPPORT) */
6063
/* All values after this line are for the debug interpreter only - add general values above this line */
6164
GOTO_EXECUTE_BREAKPOINTED_BYTECODE,
6265
HANDLE_POP_FRAMES,

0 commit comments

Comments
 (0)