#include <assert.h>
#include <jni.h>
#include "bcverify_api.h"
#include "j9.h"
#include "j9cfg.h"
#include "rommeth.h"
#include "ut_j9scar.h"
#if JAVA_SPEC_VERSION >= 16
JNIEXPORT void JNICALL
JVM_DefineArchivedModules(JNIEnv *env, jobject obj1, jobject obj2)
{
assert(!"JVM_DefineArchivedModules unimplemented");
}
JNIEXPORT void JNICALL
JVM_LogLambdaFormInvoker(JNIEnv *env, jstring str)
{
assert(!"JVM_LogLambdaFormInvoker unimplemented");
}
JNIEXPORT jboolean JNICALL
JVM_IsDumpingClassList(JNIEnv *env)
{
return JNI_FALSE;
}
#endif
#if JAVA_SPEC_VERSION >= 11
JNIEXPORT void JNICALL
JVM_InitializeFromArchive(JNIEnv *env, jclass clz)
{
}
#endif
#if JAVA_SPEC_VERSION >= 14
typedef struct GetStackTraceElementUserData {
J9ROMClass *romClass;
J9ROMMethod *romMethod;
UDATA bytecodeOffset;
} GetStackTraceElementUserData;
static UDATA
getStackTraceElementIterator(J9VMThread *vmThread, void *voidUserData, UDATA bytecodeOffset, J9ROMClass *romClass, J9ROMMethod *romMethod, J9UTF8 *fileName, UDATA lineNumber, J9ClassLoader *classLoader, J9Class* ramClass)
{
UDATA result = J9_STACKWALK_STOP_ITERATING;
if ((NULL != romMethod)
&& J9_ARE_ALL_BITS_SET(romMethod->modifiers, J9AccMethodFrameIteratorSkip)
) {
result = J9_STACKWALK_KEEP_ITERATING;
} else {
GetStackTraceElementUserData *userData = voidUserData;
userData->romClass = romClass;
userData->romMethod = romMethod;
userData->bytecodeOffset = bytecodeOffset;
}
return result;
}
#if defined(DEBUG_BCV)
static void cfdumpBytecodePrintFunction(void *userData, char *format, ...)
{
PORT_ACCESS_FROM_PORT((J9PortLibrary*)userData);
va_list args;
char outputBuffer[512] = {0};
va_start(args, format);
j9str_vprintf(outputBuffer, 512, format, args);
va_end(args);
j9tty_printf(PORTLIB, "%s", outputBuffer);
}
#endif
JNIEXPORT jstring JNICALL
JVM_GetExtendedNPEMessage(JNIEnv *env, jthrowable throwableObj)
{
J9VMThread *vmThread = (J9VMThread *)env;
J9JavaVM *vm = vmThread->javaVM;
jobject msgObjectRef = NULL;
Trc_SC_GetExtendedNPEMessage_Entry(vmThread, throwableObj);
if (J9_ARE_ANY_BITS_SET(vm->extendedRuntimeFlags2, J9_EXTENDED_RUNTIME2_SHOW_EXTENDED_NPEMSG)) {
J9InternalVMFunctions const * const vmFuncs = vm->internalVMFunctions;
char *npeMsg = NULL;
GetStackTraceElementUserData userData = {0};
Trc_SC_GetExtendedNPEMessage_Entry2(vmThread, throwableObj);
vmFuncs->internalEnterVMFromJNI(vmThread);
userData.bytecodeOffset = UDATA_MAX;
vmFuncs->iterateStackTrace(vmThread, (j9object_t*)throwableObj, getStackTraceElementIterator, &userData, TRUE);
if ((NULL != userData.romClass)
&& (NULL != userData.romMethod)
&& (UDATA_MAX != userData.bytecodeOffset)
) {
PORT_ACCESS_FROM_VMC(vmThread);
J9NPEMessageData npeMsgData = {0};
#if defined(DEBUG_BCV)
{
U_8 *bytecodes = J9_BYTECODE_START_FROM_ROM_METHOD(userData.romMethod);
U_32 flags = 0;
#if defined(J9VM_ENV_LITTLE_ENDIAN)
flags |= BCT_LittleEndianOutput;
#else
flags |= BCT_BigEndianOutput;
#endif
j9bcutil_dumpBytecodes(PORTLIB, userData.romClass, bytecodes, 0, userData.bytecodeOffset, flags, (void *)cfdumpBytecodePrintFunction, PORTLIB, "");
}
#endif
npeMsgData.npePC = userData.bytecodeOffset;
npeMsgData.vmThread = vmThread;
npeMsgData.romClass = userData.romClass;
npeMsgData.romMethod = userData.romMethod;
npeMsg = vmFuncs->getNPEMessage(&npeMsgData);
if (NULL != npeMsg) {
j9object_t msgObject = vm->memoryManagerFunctions->j9gc_createJavaLangString(vmThread, (U_8 *)npeMsg, strlen(npeMsg), 0);
if (NULL != msgObject) {
msgObjectRef = vmFuncs->j9jni_createLocalRef(env, msgObject);
}
j9mem_free_memory(npeMsg);
}
} else {
Trc_SC_GetExtendedNPEMessage_Null_NPE_MSG(vmThread, userData.romClass, userData.romMethod, userData.bytecodeOffset);
}
vmFuncs->internalExitVMToJNI(vmThread);
}
Trc_SC_GetExtendedNPEMessage_Exit(vmThread, msgObjectRef);
return msgObjectRef;
}
#endif
#if JAVA_SPEC_VERSION >= 17
JNIEXPORT void JNICALL
JVM_DumpClassListToFile(JNIEnv *env, jstring str)
{
assert(!"JVM_DumpClassListToFile unimplemented");
}
JNIEXPORT void JNICALL
JVM_DumpDynamicArchive(JNIEnv *env, jstring str)
{
assert(!"JVM_DumpDynamicArchive unimplemented");
}
#endif
#if JAVA_SPEC_VERSION >= 18
JNIEXPORT jboolean JNICALL
JVM_IsFinalizationEnabled(JNIEnv *env)
{
jboolean isFinalizationEnabled = JNI_TRUE;
J9VMThread *currentThread = (J9VMThread*)env;
if (J9_ARE_ANY_BITS_SET(currentThread->javaVM->extendedRuntimeFlags2, J9_EXTENDED_RUNTIME2_DISABLE_FINALIZATION)) {
isFinalizationEnabled = JNI_FALSE;
}
return isFinalizationEnabled;
}
JNIEXPORT void JNICALL
JVM_ReportFinalizationComplete(JNIEnv *env, jobject obj)
{
assert(!"JVM_ReportFinalizationComplete unimplemented");
}
#endif
#if JAVA_SPEC_VERSION >= 19
JNIEXPORT void JNICALL
JVM_LoadZipLibrary(void)
{
assert(!"JVM_LoadZipLibrary unimplemented");
}
#endif