#include <assert.h>
#include "vm_api.h"
#include "j2sever.h"
#include "j9.h"
#include "hashtable_api.h"
#include "../util/ut_module.h"
#undef UT_MODULE_LOADED
#undef UT_MODULE_UNLOADED
#include "ut_j9scar.h"
#include "jclprots.h"
#include "jvminit.h"
#include "util_api.h"
#include "j9vmnls.h"
#include "j9version.h"
#if JAVA_SPEC_VERSION >= 11
#define J9TIME_NANOSECONDS_PER_SECOND ((jlong) 1000000000)
#define TIME_LONG_MAX ((jlong) 4294967295000000000LL)
#define TIME_LONG_MIN ((jlong)-4294967295000000000LL)
#define OFFSET_MAX ((jlong) 0x225C17D04LL)
#define OFFSET_MIN ((jlong) 0xFFFFFFFDDA3E82FCLL)
#define HASHTABLE_ATPUT_GENERAL_FAILURE ((UDATA) 1U)
#define HASHTABLE_ATPUT_COLLISION_FAILURE ((UDATA) 2U)
#define HASHTABLE_ATPUT_SUCCESS ((UDATA) 0U)
#define INITIAL_INTERNAL_MODULE_HASHTABLE_SIZE 1
#define INITIAL_INTERNAL_PACKAGE_HASHTABLE_SIZE 1
static UDATA hashPackageTableDelete(J9VMThread * currentThread, J9ClassLoader * classLoader, const char *packageName);
static J9Package * createPackage(J9VMThread * currentThread, J9Module * fromModule, const char *package);
static void freePackageDefinition(J9VMThread * currentThread, J9ClassLoader * classLoader, const char *packageName);
static BOOLEAN removePackageDefinition(J9VMThread * currentThread, J9Module * fromModule, const char *packageName);
static BOOLEAN addPackageDefinition(J9VMThread * currentThread, J9Module * fromModule, const char *package);
static UDATA addMulPackageDefinitions(J9VMThread * currentThread, J9Module * fromModule, const char* const* packages, U_32 numPackages);
static void removeMulPackageDefinitions(J9VMThread * currentThread, J9Module * fromModule, const char* const* packages, U_32 packagesIndex);
static UDATA addModuleDefinition(J9VMThread * currentThread, J9Module * fromModule, const char* const* packages, U_32 numPackages, jstring version);
static BOOLEAN isPackageDefined(J9VMThread * currentThread, J9ClassLoader * classLoader, const char *packageName);
static BOOLEAN areNoPackagesDefined(J9VMThread * currentThread, J9ClassLoader * classLoader, const char* const* packages, U_32 numPackages);
static UDATA exportPackageToAll(J9VMThread * currentThread, J9Module * fromModule, const char *package);
static UDATA exportPackageToAllUnamed(J9VMThread * currentThread, J9Module * fromModule, const char *package);
static UDATA exportPackageToModule(J9VMThread * currentThread, J9Module * fromModule, const char *package, J9Module * toModule);
static void trcModulesCreationPackage(J9VMThread * currentThread, J9Module * fromModule, const char *package);
static void trcModulesAddModuleExportsToAll(J9VMThread * currentThread, J9Module * fromModule, const char *package);
static void trcModulesAddModuleExportsToAllUnnamed(J9VMThread * currentThread, J9Module * fromModule, const char *package);
static void trcModulesAddModuleExports(J9VMThread * currentThread, J9Module * fromModule, const char *package, J9Module * toModule);
static void trcModulesAddModulePackage(J9VMThread *currentThread, J9Module *j9mod, const char *package);
static UDATA hashTableAtPut(J9HashTable * table, void * value, BOOLEAN collisionIsFailure);
static void throwExceptionHelper(J9VMThread * currentThread, UDATA errCode);
static void freePackage(J9VMThread * currentThread, J9Package * j9package);
static J9ClassLoader * getModuleObjectClassLoader(J9VMThread * currentThread, j9object_t moduleObject);
static J9Module * createModule(J9VMThread * currentThread, j9object_t moduleObject, J9ClassLoader * classLoader, j9object_t moduleName);
static J9Module * getJ9Module(J9VMThread * currentThread, jobject module);
static BOOLEAN isModuleNameValid(j9object_t moduleName);
static BOOLEAN isModuleJavaBase(j9object_t moduleName);
static BOOLEAN isModuleNameGood(j9object_t moduleName);
static UDATA allowReadAccessToModule(J9VMThread * currentThread, J9Module * fromModule, J9Module * toModule);
static void trcModulesAddReadsModule(J9VMThread *currentThread, jobject toModule, J9Module *j9FromMod, J9Module *j9ToMod);
#if !defined(CALL_BUNDLED_FUNCTIONS_DIRECTLY)
extern IDATA (*f_monitorEnter)(omrthread_monitor_t monitor);
extern IDATA (*f_monitorExit)(omrthread_monitor_t monitor);
#endif
static UDATA
hashTableAtPut(J9HashTable * table, void * value, BOOLEAN collisionIsFailure)
{
UDATA retval = HASHTABLE_ATPUT_GENERAL_FAILURE;
void * node = NULL;
node = hashTableFind(table, value);
if (NULL == node) {
node = hashTableAdd(table, value);
if (NULL != node) {
retval = HASHTABLE_ATPUT_SUCCESS;
}
} else if (collisionIsFailure) {
retval = HASHTABLE_ATPUT_COLLISION_FAILURE;
} else {
Trc_MODULE_hashTableAtPut(table, value, node);
retval = HASHTABLE_ATPUT_SUCCESS;
}
return retval;
}
static UDATA
hashPackageTableDelete(J9VMThread * currentThread, J9ClassLoader * classLoader, const char *packageName)
{
J9HashTable * table = classLoader->packageHashTable;
J9Package package = {0};
J9Package * packagePtr = &package;
PORT_ACCESS_FROM_VMC(currentThread);
UDATA rc = 1;
U_8 buf[J9VM_PACKAGE_NAME_BUFFER_LENGTH];
if (!addUTFNameToPackage(currentThread, packagePtr, packageName, buf, J9VM_PACKAGE_NAME_BUFFER_LENGTH)) {
return rc;
}
rc = hashTableRemove(table, &package);
if ((U_8 *) package.packageName != (U_8 *)buf) {
j9mem_free_memory((void *) package.packageName);
}
return rc;
}
static void
throwExceptionHelper(J9VMThread * currentThread, UDATA errCode)
{
J9JavaVM const * const vm = currentThread->javaVM;
J9InternalVMFunctions const * const vmFuncs = vm->internalVMFunctions;
J9_DECLARE_CONSTANT_UTF8(errGeneralFailure, "general failure");
J9_DECLARE_CONSTANT_UTF8(errPackageAlreadyDefined, "a package in the list has already been define");
J9_DECLARE_CONSTANT_UTF8(errModuleAlreadyDefined, "the module has already been defined");
J9_DECLARE_CONSTANT_UTF8(errHashTableOperationFailed, "hash operation failed");
J9_DECLARE_CONSTANT_UTF8(errDuplicatePackageInList, "the list contains duplicate packages");
J9_DECLARE_CONSTANT_UTF8(errModuleWasntFound, "module was not found");
J9_DECLARE_CONSTANT_UTF8(errPackageWasntFound, "package was not found");
static J9UTF8 const * const errMessages[] = {
NULL,
(J9UTF8*)&errGeneralFailure,
(J9UTF8*)&errPackageAlreadyDefined,
(J9UTF8*)&errModuleAlreadyDefined,
(J9UTF8*)&errHashTableOperationFailed,
(J9UTF8*)&errDuplicatePackageInList,
(J9UTF8*)&errModuleWasntFound,
(J9UTF8*)&errPackageWasntFound
};
if (ERRCODE_SUCCESS != errCode) {
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGILLEGALARGUMENTEXCEPTION, (const char*)errMessages[errCode]);
}
}
static void
freePackage(J9VMThread * currentThread, J9Package * j9package)
{
if (NULL != j9package) {
J9JavaVM * const vm = currentThread->javaVM;
PORT_ACCESS_FROM_JAVAVM(vm);
if (NULL != j9package->exportsHashTable) {
hashTableFree(j9package->exportsHashTable);
}
j9mem_free_memory((void *) j9package->packageName);
pool_removeElement(vm->modularityPool, j9package);
}
}
static J9Package *
createPackage(J9VMThread * currentThread, J9Module * fromModule, const char *package)
{
J9JavaVM * const vm = currentThread->javaVM;
J9InternalVMFunctions const * const vmFuncs = vm->internalVMFunctions;
J9Package * retval = NULL;
J9ClassLoader * const classLoader = fromModule->classLoader;
J9Package * j9package = pool_newElement(vm->modularityPool);
if (NULL != j9package) {
j9package->module = fromModule;
j9package->classLoader = fromModule->classLoader;
if (!addUTFNameToPackage(currentThread, j9package, package, NULL, 0)) {
freePackage(currentThread, j9package);
return retval;
}
j9package->exportsHashTable = vmFuncs->hashModulePointerTableNew(vm, INITIAL_INTERNAL_MODULE_HASHTABLE_SIZE);
if (NULL != j9package->exportsHashTable) {
retval = j9package;
}
}
if (NULL == retval) {
if (NULL != j9package) {
freePackage(currentThread, j9package);
}
vmFuncs->setNativeOutOfMemoryError(currentThread, 0, 0);
}
return retval;
}
static J9ClassLoader *
getModuleObjectClassLoader(J9VMThread * currentThread, j9object_t moduleObject)
{
j9object_t classLoader = J9VMJAVALANGMODULE_LOADER(currentThread, moduleObject);
if (NULL == classLoader) {
return currentThread->javaVM->systemClassLoader;
} else {
J9ClassLoader *loader = J9VMJAVALANGCLASSLOADER_VMREF(currentThread, classLoader);
if (NULL == loader) {
J9JavaVM * const vm = currentThread->javaVM;
loader = vm->internalVMFunctions->internalAllocateClassLoader(vm, classLoader);
}
return loader;
}
}
static J9Module *
createModule(J9VMThread * currentThread, j9object_t moduleObject, J9ClassLoader * classLoader, j9object_t moduleName)
{
J9JavaVM * const vm = currentThread->javaVM;
J9InternalVMFunctions const * const vmFuncs = vm->internalVMFunctions;
J9Module * j9mod = NULL;
J9Module * retval = NULL;
if (J9_ARE_ALL_BITS_SET(vm->runtimeFlags, J9_RUNTIME_JAVA_BASE_MODULE_CREATED)) {
j9mod = pool_newElement(vm->modularityPool);
} else {
if (NULL == moduleName) {
j9mod = vm->unamedModuleForSystemLoader;
} else {
j9mod = vm->javaBaseModule;
j9mod->isLoose = TRUE;
}
}
if (NULL != j9mod) {
j9mod->moduleName = moduleName;
j9mod->readAccessHashTable = vmFuncs->hashModulePointerTableNew(vm, INITIAL_INTERNAL_MODULE_HASHTABLE_SIZE);
if (NULL != j9mod->readAccessHashTable) {
j9mod->classLoader = classLoader;
j9mod->moduleObject = moduleObject;
J9OBJECT_ADDRESS_STORE(currentThread, moduleObject, vm->modulePointerOffset, j9mod);
retval = j9mod;
}
}
if (NULL == retval) {
if (NULL != j9mod) {
vmFuncs->freeJ9Module(vm, j9mod);
}
vmFuncs->setNativeOutOfMemoryError(currentThread, 0, 0);
}
return retval;
}
static void
freePackageDefinition(J9VMThread * currentThread, J9ClassLoader * classLoader, const char *packageName)
{
J9Package * j9package = hashPackageTableAt(currentThread, classLoader, packageName);
if (NULL != j9package) {
freePackage(currentThread, j9package);
}
}
static BOOLEAN
removePackageDefinition(J9VMThread * currentThread, J9Module * fromModule, const char *packageName)
{
J9ClassLoader * const classLoader = fromModule->classLoader;
BOOLEAN const retval = (0 == hashPackageTableDelete(currentThread, classLoader, packageName));
freePackageDefinition(currentThread, classLoader, packageName);
return retval;
}
static void
trcModulesCreationPackage(J9VMThread * currentThread, J9Module * fromModule, const char *package)
{
PORT_ACCESS_FROM_VMC(currentThread);
J9InternalVMFunctions const * const vmFuncs = currentThread->javaVM->internalVMFunctions;
char moduleNameBuf[J9VM_PACKAGE_NAME_BUFFER_LENGTH];
char *moduleNameUTF = vmFuncs->copyStringToUTF8WithMemAlloc(
currentThread, fromModule->moduleName, J9_STR_NULL_TERMINATE_RESULT, "", 0, moduleNameBuf, J9VM_PACKAGE_NAME_BUFFER_LENGTH, NULL);
if (NULL != moduleNameUTF) {
if (0 == strcmp(moduleNameUTF, JAVA_BASE_MODULE)) {
Trc_MODULE_createPackage(currentThread, package, "java.base", fromModule);
} else {
Trc_MODULE_createPackage(currentThread, package, moduleNameUTF, fromModule);
}
if (moduleNameBuf != moduleNameUTF) {
j9mem_free_memory(moduleNameUTF);
}
} else {
vmFuncs->setNativeOutOfMemoryError(currentThread, 0, 0);
}
}
static BOOLEAN
addPackageDefinition(J9VMThread * currentThread, J9Module * fromModule, const char *package)
{
J9ClassLoader * const classLoader = fromModule->classLoader;
BOOLEAN retval = FALSE;
J9Package * j9package = createPackage(currentThread, fromModule, package);
if (NULL != j9package) {
Trc_MODULE_invokeHashTableAtPut(currentThread, "addPackageDefinition", classLoader, classLoader->packageHashTable, &j9package, j9package, "true");
retval = (0 == hashTableAtPut(classLoader->packageHashTable, (void*)&j9package, TRUE));
}
if (!retval) {
freePackage(currentThread, j9package);
} else {
if (TrcEnabled_Trc_MODULE_createPackage) {
trcModulesCreationPackage(currentThread, fromModule, package);
}
}
return retval;
}
static void
removeMulPackageDefinitions(J9VMThread * currentThread, J9Module * fromModule, const char* const* packages, U_32 packagesIndex)
{
BOOLEAN stopLoop = FALSE;
U_32 i = packagesIndex;
while (!stopLoop) {
const char *packageName = packages[i];
Assert_SC_true(removePackageDefinition(currentThread, fromModule, packageName));
stopLoop = (0 == i);
--i;
}
}
static UDATA
addMulPackageDefinitions(J9VMThread * currentThread, J9Module * fromModule, const char* const* packages, U_32 numPackages)
{
UDATA retval = ERRCODE_SUCCESS;
if (NULL != packages) {
U_32 const arrayLength = numPackages;
if (0 != arrayLength) {
U_32 i = 0;
for (i = 0; i < arrayLength; i++) {
const char *packageName = packages[i];
if (!addPackageDefinition(currentThread, fromModule, packageName)) {
J9ClassLoader * const classLoader = fromModule->classLoader;
if (isPackageDefined(currentThread, classLoader, packageName)) {
retval = ERRCODE_DUPLICATE_PACKAGE_IN_LIST;
}
break;
}
}
if (ERRCODE_SUCCESS != retval) {
if (i > 0) {
--i;
removeMulPackageDefinitions(currentThread, fromModule, packages, i);
}
}
}
}
return retval;
}
static UDATA
addModuleDefinition(J9VMThread * currentThread, J9Module * fromModule, const char* const* packages, U_32 numPackages, jstring version)
{
J9ClassLoader * const classLoader = fromModule->classLoader;
UDATA retval = ERRCODE_GENERAL_FAILURE;
if (!areNoPackagesDefined(currentThread, classLoader, packages, numPackages)) {
retval = ERRCODE_PACKAGE_ALREADY_DEFINED;
} else if (isModuleDefined(currentThread, fromModule)) {
retval = ERRCODE_MODULE_ALREADY_DEFINED;
} else {
retval = addMulPackageDefinitions(currentThread, fromModule, packages, numPackages);
if (ERRCODE_SUCCESS == retval) {
BOOLEAN const success = (0 == hashTableAtPut(classLoader->moduleHashTable, (void*)&fromModule, TRUE));
Trc_MODULE_invokeHashTableAtPut(currentThread, "addModuleDefinition", classLoader, classLoader->moduleHashTable, &fromModule, fromModule, "true");
if (NULL != version) {
fromModule->version = J9_JNI_UNWRAP_REFERENCE(version);
}
if (!success) {
if (NULL != packages) {
removeMulPackageDefinitions(currentThread, fromModule, packages, numPackages);
}
retval = ERRCODE_HASHTABLE_OPERATION_FAILED;
}
}
}
return retval;
}
static BOOLEAN
isPackageDefined(J9VMThread * currentThread, J9ClassLoader * classLoader, const char *packageName)
{
J9Package const * target = NULL;
target = hashPackageTableAt(currentThread, classLoader, packageName);
return (NULL != target);
}
static BOOLEAN
areNoPackagesDefined(J9VMThread * currentThread, J9ClassLoader * classLoader, const char* const* packages, U_32 numPackages)
{
BOOLEAN success = TRUE;
J9JavaVM * vm = currentThread->javaVM;
J9InternalVMFunctions const * const vmFuncs = vm->internalVMFunctions;
BOOLEAN checkDefinedPackages = J9_ARE_ALL_BITS_SET(vm->runtimeFlags, J9_RUNTIME_JAVA_BASE_MODULE_CREATED);
if (NULL != packages) {
U_32 const arrayLength = numPackages;
if (0 != arrayLength) {
U_32 i = 0;
for (i = 0; success && (i < arrayLength); i++) {
const char *packageName = packages[i];
if (checkDefinedPackages
&& vmFuncs->isAnyClassLoadedFromPackage(classLoader, (U_8*) packageName, strlen(packageName))
) {
success = FALSE;
}
}
}
}
return success;
}
static void
trcModulesAddModuleExportsToAll(J9VMThread * currentThread, J9Module * fromModule, const char *package)
{
PORT_ACCESS_FROM_VMC(currentThread);
J9InternalVMFunctions const * const vmFuncs = currentThread->javaVM->internalVMFunctions;
char fromModuleNameBuf[J9VM_PACKAGE_NAME_BUFFER_LENGTH];
char *fromModuleNameUTF = vmFuncs->copyStringToUTF8WithMemAlloc(
currentThread, fromModule->moduleName, J9_STR_NULL_TERMINATE_RESULT, "", 0, fromModuleNameBuf, J9VM_PACKAGE_NAME_BUFFER_LENGTH, NULL);
if (NULL != fromModuleNameUTF) {
Trc_MODULE_addModuleExportsToAll(currentThread, package, fromModuleNameUTF, fromModule);
if (fromModuleNameBuf != fromModuleNameUTF) {
j9mem_free_memory(fromModuleNameUTF);
}
}
}
static UDATA
exportPackageToAll(J9VMThread * currentThread, J9Module * fromModule, const char *package)
{
UDATA retval = ERRCODE_GENERAL_FAILURE;
J9Package * const j9package = getPackageDefinition(currentThread, fromModule, package, &retval);
if (NULL != j9package) {
j9package->exportToAll = 1;
if (TrcEnabled_Trc_MODULE_addModuleExportsToAll) {
trcModulesAddModuleExportsToAll(currentThread, fromModule, package);
}
}
return retval;
}
static void
trcModulesAddModuleExportsToAllUnnamed(J9VMThread * currentThread, J9Module * fromModule, const char *package)
{
PORT_ACCESS_FROM_VMC(currentThread);
J9InternalVMFunctions const * const vmFuncs = currentThread->javaVM->internalVMFunctions;
char fromModuleNameBuf[J9VM_PACKAGE_NAME_BUFFER_LENGTH];
char *fromModuleNameUTF = vmFuncs->copyStringToUTF8WithMemAlloc(
currentThread, fromModule->moduleName, J9_STR_NULL_TERMINATE_RESULT, "", 0, fromModuleNameBuf, J9VM_PACKAGE_NAME_BUFFER_LENGTH, NULL);
if (NULL != fromModuleNameUTF) {
Trc_MODULE_addModuleExportsToAllUnnamed(currentThread, package, fromModuleNameUTF, fromModule);
if (fromModuleNameBuf != fromModuleNameUTF) {
j9mem_free_memory(fromModuleNameUTF);
}
}
}
static UDATA
exportPackageToAllUnamed(J9VMThread * currentThread, J9Module * fromModule, const char *package)
{
UDATA retval = ERRCODE_GENERAL_FAILURE;
J9Package * const j9package = getPackageDefinition(currentThread, fromModule, package, &retval);
if (NULL != j9package) {
j9package->exportToAllUnnamed = 1;
if (TrcEnabled_Trc_MODULE_addModuleExportsToAllUnnamed) {
trcModulesAddModuleExportsToAllUnnamed(currentThread, fromModule, package);
}
}
return retval;
}
static J9Module *
getJ9Module(J9VMThread * currentThread, jobject module)
{
J9JavaVM const * const vm = currentThread->javaVM;
j9object_t modObj = J9_JNI_UNWRAP_REFERENCE(module);
return J9OBJECT_ADDRESS_LOAD(currentThread, modObj, vm->modulePointerOffset);
}
static BOOLEAN
isModuleJavaBase(j9object_t moduleName)
{
return FALSE;
}
static BOOLEAN
isModuleNameGood(j9object_t moduleName)
{
return TRUE;
}
static BOOLEAN
isModuleNameValid(j9object_t moduleName)
{
BOOLEAN retval = FALSE;
if (NULL != moduleName) {
retval = TRUE;
if (!isModuleJavaBase(moduleName)) {
retval = isModuleNameGood(moduleName);
}
}
return retval;
}
static void
trcModulesAddModuleExports(J9VMThread *currentThread, J9Module *fromModule, const char *package, J9Module *toModule)
{
PORT_ACCESS_FROM_VMC(currentThread);
J9InternalVMFunctions const * const vmFuncs = currentThread->javaVM->internalVMFunctions;
char fromModuleNameBuf[J9VM_PACKAGE_NAME_BUFFER_LENGTH];
char toModuleNameBuf[J9VM_PACKAGE_NAME_BUFFER_LENGTH];
char *fromModuleNameUTF = vmFuncs->copyStringToUTF8WithMemAlloc(
currentThread, fromModule->moduleName, J9_STR_NULL_TERMINATE_RESULT, "", 0, fromModuleNameBuf, J9VM_PACKAGE_NAME_BUFFER_LENGTH, NULL);
char *toModuleNameUTF = vmFuncs->copyStringToUTF8WithMemAlloc(
currentThread, toModule->moduleName, J9_STR_NULL_TERMINATE_RESULT, "", 0, toModuleNameBuf, J9VM_PACKAGE_NAME_BUFFER_LENGTH, NULL);
if ((NULL != fromModuleNameUTF) && (NULL != toModuleNameUTF)) {
Trc_MODULE_addModuleExports(currentThread, package, fromModuleNameUTF, fromModule, toModuleNameUTF, toModule);
}
if (fromModuleNameBuf != fromModuleNameUTF) {
j9mem_free_memory(fromModuleNameUTF);
}
if (toModuleNameBuf != toModuleNameUTF) {
j9mem_free_memory(toModuleNameUTF);
}
}
static UDATA
exportPackageToModule(J9VMThread * currentThread, J9Module * fromModule, const char *package, J9Module * toModule)
{
UDATA retval = ERRCODE_GENERAL_FAILURE;
J9Package * const j9package = getPackageDefinition(currentThread, fromModule, package, &retval);
if (NULL != j9package) {
if (isModuleDefined(currentThread, toModule)) {
Trc_MODULE_invokeHashTableAtPut(currentThread, "exportPackageToModule(exportsHashTable)", j9package, j9package->exportsHashTable, &toModule, toModule, "false");
if (0 == hashTableAtPut(j9package->exportsHashTable, (void*)&toModule, FALSE)) {
retval = ERRCODE_SUCCESS;
if (NULL == toModule->removeExportsHashTable) {
J9JavaVM *vm = currentThread->javaVM;
toModule->removeExportsHashTable = vm->internalVMFunctions->hashPackageTableNew(vm, INITIAL_INTERNAL_PACKAGE_HASHTABLE_SIZE);
}
if (NULL != toModule->removeExportsHashTable) {
Trc_MODULE_invokeHashTableAtPut(currentThread, "exportPackageToModule(removeExportsHashTable)", toModule, toModule->removeExportsHashTable, &j9package, j9package, "false");
if (0 != hashTableAtPut(toModule->removeExportsHashTable, (void*)&j9package, FALSE)) {
retval = ERRCODE_HASHTABLE_OPERATION_FAILED;
}
} else {
retval = ERRCODE_HASHTABLE_OPERATION_FAILED;
}
} else {
retval = ERRCODE_HASHTABLE_OPERATION_FAILED;
}
} else {
retval = ERRCODE_MODULE_WASNT_FOUND;
}
}
if (ERRCODE_SUCCESS == retval && TrcEnabled_Trc_MODULE_addModuleExports) {
trcModulesAddModuleExports(currentThread, fromModule, package, toModule);
}
return retval;
}
static UDATA
allowReadAccessToModule(J9VMThread * currentThread, J9Module * fromModule, J9Module * toModule)
{
UDATA retval = ERRCODE_MODULE_WASNT_FOUND;
if (isModuleDefined(currentThread, fromModule)) {
J9JavaVM *vm = currentThread->javaVM;
if (J9_IS_J9MODULE_UNNAMED(vm, toModule)) {
fromModule->isLoose = TRUE;
retval = ERRCODE_SUCCESS;
} else if (isModuleDefined(currentThread, toModule)) {
BOOLEAN success = FALSE;
Trc_MODULE_invokeHashTableAtPut(currentThread, "allowReadAccessToModule(readAccessHashTable)", toModule, toModule->readAccessHashTable, &fromModule, fromModule, "false");
if (0 == hashTableAtPut(toModule->readAccessHashTable, (void*)&fromModule, FALSE)) {
success = TRUE;
if (NULL == fromModule->removeAccessHashTable) {
fromModule->removeAccessHashTable = vm->internalVMFunctions->hashModulePointerTableNew(vm, INITIAL_INTERNAL_MODULE_HASHTABLE_SIZE);
}
if (NULL != fromModule->removeAccessHashTable) {
Trc_MODULE_invokeHashTableAtPut(currentThread, "allowReadAccessToModule(removeAccessHashTable)", fromModule, fromModule->removeAccessHashTable, &toModule, toModule, "false");
if (0 != hashTableAtPut(fromModule->removeAccessHashTable, (void*)&toModule, FALSE)) {
success = FALSE;
}
} else {
retval = ERRCODE_HASHTABLE_OPERATION_FAILED;
}
}
if (success) {
retval = ERRCODE_SUCCESS;
} else {
retval = ERRCODE_HASHTABLE_OPERATION_FAILED;
}
}
}
return retval;
}
jobject JNICALL
#if JAVA_SPEC_VERSION >= 15
JVM_DefineModule(JNIEnv * env, jobject module, jboolean isOpen, jstring version, jstring location, jobjectArray packageArray)
#else
JVM_DefineModule(JNIEnv * env, jobject module, jboolean isOpen, jstring version, jstring location, const char* const* packages, jsize numPackages)
#endif
{
J9VMThread * const currentThread = (J9VMThread*)env;
J9JavaVM * vm = currentThread->javaVM;
J9InternalVMFunctions const * const vmFuncs = vm->internalVMFunctions;
#if JAVA_SPEC_VERSION >= 15
BOOLEAN oom = FALSE;
jsize numPackages = 0;
UDATA packagesNumBytes = 0;
const char** packages = NULL;
PORT_ACCESS_FROM_ENV(env);
#endif
vmFuncs->internalEnterVMFromJNI(currentThread);
#if defined(CALL_BUNDLED_FUNCTIONS_DIRECTLY)
omrthread_monitor_enter(vm->classLoaderModuleAndLocationMutex);
#else
f_monitorEnter(vm->classLoaderModuleAndLocationMutex);
#endif
#if JAVA_SPEC_VERSION >= 15
if (NULL != packageArray) {
numPackages = J9INDEXABLEOBJECT_SIZE(currentThread, J9_JNI_UNWRAP_REFERENCE(packageArray));
packagesNumBytes = sizeof(char*) * numPackages;
} else {
vmFuncs->setCurrentExceptionNLS(currentThread, J9VMCONSTANTPOOL_JAVALANGNULLPOINTEREXCEPTION, J9NLS_VM_PACKAGES_IS_NULL);
goto done;
}
packages = (const char**)j9mem_allocate_memory(packagesNumBytes, OMRMEM_CATEGORY_VM);
if (NULL != packages) {
jsize pkgIndex = 0;
memset((void *)packages, 0, packagesNumBytes);
for (pkgIndex = 0; pkgIndex < numPackages; pkgIndex++) {
j9array_t array = (j9array_t)J9_JNI_UNWRAP_REFERENCE(packageArray);
j9object_t stringObject = J9JAVAARRAYOFOBJECT_LOAD(currentThread, array, pkgIndex);
if (NULL != stringObject) {
UDATA utfLength = vmFuncs->getStringUTF8Length(currentThread, stringObject) + 1;
char *packageName = (char*)j9mem_allocate_memory(utfLength, OMRMEM_CATEGORY_VM);
if (NULL == packageName) {
oom = TRUE;
break;
}
vmFuncs->copyStringToUTF8Helper(currentThread, stringObject, J9_STR_NULL_TERMINATE_RESULT | J9_STR_XLAT , 0, J9VMJAVALANGSTRING_LENGTH(currentThread, stringObject), (U_8 *)packageName, utfLength);
packages[pkgIndex] = packageName;
} else {
vmFuncs->setCurrentExceptionNLS(currentThread, J9VMCONSTANTPOOL_JAVALANGNULLPOINTEREXCEPTION, J9NLS_VM_PACKAGE_IS_NULL);
goto done;
}
}
}
if ((NULL == packages) || oom) {
vmFuncs->setNativeOutOfMemoryError(currentThread, 0, 0);
goto done;
}
#endif
if (NULL == module) {
vmFuncs->setCurrentExceptionNLS(currentThread, J9VMCONSTANTPOOL_JAVALANGNULLPOINTEREXCEPTION, J9NLS_VM_MODULE_IS_NULL);
} else {
j9object_t modObj = J9_JNI_UNWRAP_REFERENCE(module);
J9ClassLoader * const classLoader = getModuleObjectClassLoader(currentThread, modObj);
j9object_t moduleName = J9VMJAVALANGMODULE_NAME(currentThread, modObj);
if ((classLoader != vm->systemClassLoader) && (classLoader != vm->extensionClassLoader)) {
jsize pkgIndex = 0;
for (pkgIndex = 0; pkgIndex < numPackages; pkgIndex++) {
const char *packageName = packages[pkgIndex];
if (0 == strncmp(packageName, "java", 4)) {
char nextCh = packageName[4];
if (('\0' == nextCh) || ('.' == nextCh) || ('/' == nextCh)) {
vmFuncs->setCurrentExceptionNLS(currentThread, J9VMCONSTANTPOOL_JAVALANGILLEGALARGUMENTEXCEPTION, J9NLS_VM_ONLY_BOOT_PLATFORM_CLASSLOADER_DEFINE_PKG_JAVA);
goto done;
}
}
}
}
if (NULL == moduleName) {
vmFuncs->setCurrentExceptionNLS(currentThread, J9VMCONSTANTPOOL_JAVALANGILLEGALARGUMENTEXCEPTION, J9NLS_VM_MODULE_IS_UNNAMED);
} else if (!isModuleNameValid(moduleName)) {
vmFuncs->setCurrentExceptionNLS(currentThread, J9VMCONSTANTPOOL_JAVALANGILLEGALARGUMENTEXCEPTION, J9NLS_VM_MODULE_NAME_IS_INVALID);
} else if (NULL == classLoader) {
Assert_SC_true(NULL != currentThread->currentException);
} else {
char buf[J9VM_PACKAGE_NAME_BUFFER_LENGTH];
char *nameUTF = buf;
PORT_ACCESS_FROM_VMC(currentThread);
nameUTF = vmFuncs->copyStringToUTF8WithMemAlloc(
currentThread, moduleName, J9_STR_NULL_TERMINATE_RESULT, "", 0, buf, J9VM_PACKAGE_NAME_BUFFER_LENGTH, NULL);
if (NULL == nameUTF) {
vmFuncs->setNativeOutOfMemoryError(currentThread, 0, 0);
} else if ((classLoader != vm->systemClassLoader) && (0 == strcmp(nameUTF, JAVA_BASE_MODULE))) {
vmFuncs->setCurrentExceptionNLS(currentThread, J9VMCONSTANTPOOL_JAVALANGLAYERINSTANTIATIONEXCEPTION, J9NLS_VM_ONLY_BOOTCLASSLOADER_LOAD_MODULE_JAVABASE);
} else {
J9Module *j9mod = createModule(currentThread, modObj, classLoader, moduleName);
if (NULL != j9mod) {
BOOLEAN success = FALSE;
UDATA rc = addModuleDefinition(currentThread, j9mod, packages, (U_32) numPackages, version);
j9mod->isOpen = isOpen;
success = (ERRCODE_SUCCESS == rc);
if (success) {
if (J9_ARE_ALL_BITS_SET(vm->runtimeFlags, J9_RUNTIME_JAVA_BASE_MODULE_CREATED)) {
Trc_MODULE_defineModule(currentThread, nameUTF, j9mod);
if (classLoader == vm->systemClassLoader) {
success = vmFuncs->setBootLoaderModulePatchPaths(vm, j9mod, (const char *)nameUTF);
if (FALSE == success) {
vmFuncs->setNativeOutOfMemoryError(currentThread, 0, 0);
} else {
const char* moduleName = "openj9.sharedclasses";
if (0 == strcmp(nameUTF, moduleName)) {
J9VMDllLoadInfo *entry = FIND_DLL_TABLE_ENTRY(J9_SHARED_DLL_NAME);
if ((NULL == entry)
|| (J9_ARE_ALL_BITS_SET(entry->loadFlags, FAILED_TO_LOAD))
) {
j9nls_printf(PORTLIB, J9NLS_WARNING, J9NLS_VM_FAILED_TO_LOAD_MODULE_REQUIRED_DLL, J9_SHARED_DLL_NAME, moduleName);
}
}
}
}
} else {
J9ClassWalkState classWalkState;
J9Class* clazz = NULL;
Assert_SC_true(0 == strcmp(nameUTF, JAVA_BASE_MODULE));
clazz = vmFuncs->allClassesStartDo(&classWalkState, vm, vm->systemClassLoader);
while (NULL != clazz) {
Assert_SC_true(clazz->module == vm->javaBaseModule);
J9VMJAVALANGCLASS_SET_MODULE(currentThread, clazz->classObject, modObj);
clazz = vmFuncs->allClassesNextDo(&classWalkState);
}
vmFuncs->allClassesEndDo(&classWalkState);
if (vm->anonClassCount > 0) {
J9ClassWalkState classWalkStateAnon = {0};
J9Class *clazzAnon = NULL;
Assert_SC_notNull(vm->anonClassLoader);
clazzAnon = vmFuncs->allClassesStartDo(&classWalkStateAnon, vm, vm->anonClassLoader);
while (NULL != clazzAnon) {
Assert_SC_true(clazzAnon->module == vm->javaBaseModule);
J9VMJAVALANGCLASS_SET_MODULE(currentThread, clazzAnon->classObject, modObj);
clazzAnon = vmFuncs->allClassesNextDo(&classWalkStateAnon);
}
vmFuncs->allClassesEndDo(&classWalkStateAnon);
}
vm->runtimeFlags |= J9_RUNTIME_JAVA_BASE_MODULE_CREATED;
Trc_MODULE_defineModule(currentThread, "java.base", j9mod);
}
TRIGGER_J9HOOK_VM_MODULE_LOAD(vm->hookInterface, currentThread, j9mod);
} else {
throwExceptionHelper(currentThread, rc);
}
if (FALSE == success) {
vmFuncs->freeJ9Module(vm, j9mod);
Assert_SC_true(NULL != currentThread->currentException);
}
}
}
if (nameUTF != buf) {
j9mem_free_memory(nameUTF);
}
}
}
done:
#if JAVA_SPEC_VERSION >= 15
if (NULL != packages) {
jsize pkgIndex = 0;
for (pkgIndex = 0; pkgIndex < numPackages; pkgIndex++) {
const char* packageName = packages[pkgIndex];
j9mem_free_memory((void *)packageName);
}
j9mem_free_memory((void *)packages);
}
#endif
#if defined(CALL_BUNDLED_FUNCTIONS_DIRECTLY)
omrthread_monitor_exit(vm->classLoaderModuleAndLocationMutex);
#else
f_monitorExit(vm->classLoaderModuleAndLocationMutex);
#endif
vmFuncs->internalExitVMToJNI(currentThread);
return module;
}
#if JAVA_SPEC_VERSION >= 15
void JNICALL
JVM_AddModuleExports(JNIEnv * env, jobject fromModule, jstring packageObj, jobject toModule)
#else
void JNICALL
JVM_AddModuleExports(JNIEnv * env, jobject fromModule, const char *package, jobject toModule)
#endif
{
J9VMThread * const currentThread = (J9VMThread*)env;
J9JavaVM const * const vm = currentThread->javaVM;
J9InternalVMFunctions const * const vmFuncs = vm->internalVMFunctions;
#if JAVA_SPEC_VERSION >= 15
const char *package = NULL;
PORT_ACCESS_FROM_ENV(env);
#endif
vmFuncs->internalEnterVMFromJNI(currentThread);
#if defined(CALL_BUNDLED_FUNCTIONS_DIRECTLY)
omrthread_monitor_enter(vm->classLoaderModuleAndLocationMutex);
#else
f_monitorEnter(vm->classLoaderModuleAndLocationMutex);
#endif
#if JAVA_SPEC_VERSION >= 15
if (NULL != packageObj) {
j9object_t stringObject = J9_JNI_UNWRAP_REFERENCE(packageObj);
UDATA utfLength = vmFuncs->getStringUTF8Length(currentThread, stringObject) + 1;
char* packageName = (char *)j9mem_allocate_memory(utfLength, OMRMEM_CATEGORY_VM);
if (NULL == packageName) {
vmFuncs->setNativeOutOfMemoryError(currentThread, 0, 0);
goto done;
}
vmFuncs->copyStringToUTF8Helper(currentThread, stringObject, J9_STR_NULL_TERMINATE_RESULT | J9_STR_XLAT , 0, J9VMJAVALANGSTRING_LENGTH(currentThread, stringObject), (U_8 *)packageName, utfLength);
package = packageName;
} else {
vmFuncs->setCurrentExceptionNLS(currentThread, J9VMCONSTANTPOOL_JAVALANGNULLPOINTEREXCEPTION, J9NLS_VM_PACKAGE_IS_NULL);
goto done;
}
#endif
if (NULL == toModule) {
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGNULLPOINTEREXCEPTION, "module is null");
} else {
UDATA rc = ERRCODE_GENERAL_FAILURE;
J9Module * const j9FromMod = getJ9Module(currentThread, fromModule);
J9Module * const j9ToMod = getJ9Module(currentThread, toModule);
if (isModuleUnnamed(currentThread, J9_JNI_UNWRAP_REFERENCE(toModule))) {
rc = exportPackageToAllUnamed(currentThread, j9FromMod, package);
} else {
rc = exportPackageToModule(currentThread, j9FromMod, package, j9ToMod);
}
if (ERRCODE_SUCCESS != rc) {
throwExceptionHelper(currentThread, rc);
}
}
#if JAVA_SPEC_VERSION >= 15
done:
if (NULL != package) {
j9mem_free_memory((void*)package);
}
#endif
#if defined(CALL_BUNDLED_FUNCTIONS_DIRECTLY)
omrthread_monitor_exit(vm->classLoaderModuleAndLocationMutex);
#else
f_monitorExit(vm->classLoaderModuleAndLocationMutex);
#endif
vmFuncs->internalExitVMToJNI(currentThread);
}
#if JAVA_SPEC_VERSION >= 15
void JNICALL
JVM_AddModuleExportsToAll(JNIEnv * env, jobject fromModule, jstring packageObj)
#else
void JNICALL
JVM_AddModuleExportsToAll(JNIEnv * env, jobject fromModule, const char *package)
#endif
{
J9VMThread * const currentThread = (J9VMThread*)env;
J9JavaVM const * const vm = currentThread->javaVM;
J9InternalVMFunctions const * const vmFuncs = vm->internalVMFunctions;
#if JAVA_SPEC_VERSION >= 15
const char *package = NULL;
PORT_ACCESS_FROM_ENV(env);
#endif
vmFuncs->internalEnterVMFromJNI(currentThread);
#if defined(CALL_BUNDLED_FUNCTIONS_DIRECTLY)
omrthread_monitor_enter(vm->classLoaderModuleAndLocationMutex);
#else
f_monitorEnter(vm->classLoaderModuleAndLocationMutex);
#endif
#if JAVA_SPEC_VERSION >= 15
if (NULL != packageObj) {
j9object_t stringObject = J9_JNI_UNWRAP_REFERENCE(packageObj);
UDATA utfLength = vmFuncs->getStringUTF8Length(currentThread, stringObject) + 1;
char* packageName = (char *)j9mem_allocate_memory(utfLength, OMRMEM_CATEGORY_VM);
if (NULL == packageName) {
vmFuncs->setNativeOutOfMemoryError(currentThread, 0, 0);
goto done;
}
vmFuncs->copyStringToUTF8Helper(currentThread, stringObject, J9_STR_NULL_TERMINATE_RESULT | J9_STR_XLAT , 0, J9VMJAVALANGSTRING_LENGTH(currentThread, stringObject), (U_8 *)packageName, utfLength);
package = packageName;
} else {
vmFuncs->setCurrentExceptionNLS(currentThread, J9VMCONSTANTPOOL_JAVALANGNULLPOINTEREXCEPTION, J9NLS_VM_PACKAGE_IS_NULL);
goto done;
}
#endif
{
UDATA rc = ERRCODE_GENERAL_FAILURE;
J9Module * const j9FromMod = getJ9Module(currentThread, fromModule);
rc = exportPackageToAll(currentThread, j9FromMod, package);
if (ERRCODE_SUCCESS != rc) {
throwExceptionHelper(currentThread, rc);
}
}
#if JAVA_SPEC_VERSION >= 15
done:
if (NULL != package) {
j9mem_free_memory((void*)package);
}
#endif
#if defined(CALL_BUNDLED_FUNCTIONS_DIRECTLY)
omrthread_monitor_exit(vm->classLoaderModuleAndLocationMutex);
#else
f_monitorExit(vm->classLoaderModuleAndLocationMutex);
#endif
vmFuncs->internalExitVMToJNI(currentThread);
}
static void
trcModulesAddReadsModule(J9VMThread *currentThread, jobject toModule, J9Module *j9FromMod, J9Module *j9ToMod)
{
PORT_ACCESS_FROM_VMC(currentThread);
J9InternalVMFunctions const * const vmFuncs = currentThread->javaVM->internalVMFunctions;
char fromModuleNameBuf[J9VM_PACKAGE_NAME_BUFFER_LENGTH];
char toModuleNameBuf[J9VM_PACKAGE_NAME_BUFFER_LENGTH];
char *fromModuleNameUTF = vmFuncs->copyStringToUTF8WithMemAlloc(
currentThread, j9FromMod->moduleName, J9_STR_NULL_TERMINATE_RESULT, "", 0, fromModuleNameBuf, J9VM_PACKAGE_NAME_BUFFER_LENGTH, NULL);
char *toModuleNameUTF = NULL;
if (NULL != j9ToMod) {
if (NULL != j9ToMod->moduleName) {
toModuleNameUTF = vmFuncs->copyStringToUTF8WithMemAlloc(
currentThread, j9ToMod->moduleName, J9_STR_NULL_TERMINATE_RESULT, "", 0, toModuleNameBuf, J9VM_PACKAGE_NAME_BUFFER_LENGTH, NULL);
} else {
#define UNNAMED_MODULE "unnamed "
PORT_ACCESS_FROM_VMC(currentThread);
Assert_SC_true(J9VM_PACKAGE_NAME_BUFFER_LENGTH >= sizeof(UNNAMED_MODULE));
memcpy(toModuleNameBuf, UNNAMED_MODULE, sizeof(UNNAMED_MODULE));
toModuleNameUTF = toModuleNameBuf;
#undef UNNAMED_MODULE
}
} else {
#define LOOSE_MODULE "loose "
PORT_ACCESS_FROM_VMC(currentThread);
Assert_SC_true(J9VM_PACKAGE_NAME_BUFFER_LENGTH >= sizeof(LOOSE_MODULE));
memcpy(toModuleNameBuf, LOOSE_MODULE, sizeof(LOOSE_MODULE));
toModuleNameUTF = toModuleNameBuf;
#undef LOOSE_MODULE
}
if ((NULL != fromModuleNameUTF) && (NULL != toModuleNameUTF)) {
Trc_MODULE_addReadsModule(currentThread, fromModuleNameUTF, j9FromMod, toModuleNameUTF, toModule);
}
if (fromModuleNameBuf != fromModuleNameUTF) {
j9mem_free_memory(fromModuleNameUTF);
}
if (toModuleNameBuf != toModuleNameUTF) {
j9mem_free_memory(toModuleNameUTF);
}
}
void JNICALL
JVM_AddReadsModule(JNIEnv * env, jobject fromModule, jobject toModule)
{
if (fromModule != toModule) {
J9VMThread * const currentThread = (J9VMThread*)env;
J9JavaVM const * const vm = currentThread->javaVM;
J9InternalVMFunctions const * const vmFuncs = vm->internalVMFunctions;
vmFuncs->internalEnterVMFromJNI(currentThread);
#if defined(CALL_BUNDLED_FUNCTIONS_DIRECTLY)
omrthread_monitor_enter(vm->classLoaderModuleAndLocationMutex);
#else
f_monitorEnter(vm->classLoaderModuleAndLocationMutex);
#endif
{
UDATA rc = ERRCODE_GENERAL_FAILURE;
J9Module * const j9FromMod = getJ9Module(currentThread, fromModule);
J9Module * const j9ToMod = (NULL != toModule) ? getJ9Module(currentThread, toModule) : NULL;
if (j9FromMod != j9ToMod) {
rc = allowReadAccessToModule(currentThread, j9FromMod, j9ToMod);
if (ERRCODE_SUCCESS != rc) {
throwExceptionHelper(currentThread, rc);
} else {
if (TrcEnabled_Trc_MODULE_addReadsModule) {
trcModulesAddReadsModule(currentThread, toModule, j9FromMod, j9ToMod);
}
}
}
}
#if defined(CALL_BUNDLED_FUNCTIONS_DIRECTLY)
omrthread_monitor_exit(vm->classLoaderModuleAndLocationMutex);
#else
f_monitorExit(vm->classLoaderModuleAndLocationMutex);
#endif
vmFuncs->internalExitVMToJNI(currentThread);
}
}
jboolean JNICALL
JVM_CanReadModule(JNIEnv * env, jobject askModule, jobject srcModule)
{
J9VMThread * const currentThread = (J9VMThread*)env;
J9JavaVM const * const vm = currentThread->javaVM;
J9InternalVMFunctions const * const vmFuncs = vm->internalVMFunctions;
BOOLEAN canRead = FALSE;
if (askModule == srcModule) {
canRead = TRUE;
} else {
vmFuncs->internalEnterVMFromJNI(currentThread);
#if defined(CALL_BUNDLED_FUNCTIONS_DIRECTLY)
omrthread_monitor_enter(vm->classLoaderModuleAndLocationMutex);
#else
f_monitorEnter(vm->classLoaderModuleAndLocationMutex);
#endif
{
UDATA rc = ERRCODE_GENERAL_FAILURE;
J9Module * const j9FromMod = getJ9Module(currentThread, askModule);
J9Module * const j9ToMod = getJ9Module(currentThread, srcModule);
canRead = isAllowedReadAccessToModule(currentThread, j9FromMod, j9ToMod, &rc);
if (ERRCODE_SUCCESS != rc) {
throwExceptionHelper(currentThread, rc);
}
}
#if defined(CALL_BUNDLED_FUNCTIONS_DIRECTLY)
omrthread_monitor_exit(vm->classLoaderModuleAndLocationMutex);
#else
f_monitorExit(vm->classLoaderModuleAndLocationMutex);
#endif
vmFuncs->internalExitVMToJNI(currentThread);
}
return (jboolean)canRead;
}
static void
trcModulesAddModulePackage(J9VMThread *currentThread, J9Module *j9mod, const char *package)
{
PORT_ACCESS_FROM_VMC(currentThread);
J9InternalVMFunctions const * const vmFuncs = currentThread->javaVM->internalVMFunctions;
char moduleNameBuf[J9VM_PACKAGE_NAME_BUFFER_LENGTH];
char *moduleNameUTF = vmFuncs->copyStringToUTF8WithMemAlloc(
currentThread, j9mod->moduleName, J9_STR_NULL_TERMINATE_RESULT, "", 0, moduleNameBuf, J9VM_PACKAGE_NAME_BUFFER_LENGTH, NULL);
if (NULL != moduleNameUTF) {
Trc_MODULE_addModulePackage(currentThread, package, moduleNameUTF, j9mod);
if (moduleNameBuf != moduleNameUTF) {
j9mem_free_memory(moduleNameUTF);
}
}
}
void JNICALL
JVM_AddModulePackage(JNIEnv * env, jobject module, const char *package)
{
J9VMThread * const currentThread = (J9VMThread*)env;
J9JavaVM const * const vm = currentThread->javaVM;
J9InternalVMFunctions const * const vmFuncs = vm->internalVMFunctions;
vmFuncs->internalEnterVMFromJNI(currentThread);
#if defined(CALL_BUNDLED_FUNCTIONS_DIRECTLY)
omrthread_monitor_enter(vm->classLoaderModuleAndLocationMutex);
#else
f_monitorEnter(vm->classLoaderModuleAndLocationMutex);
#endif
{
J9Module * const j9mod = getJ9Module(currentThread, module);
UDATA rc = addPackageDefinition(currentThread, j9mod, package);
if (ERRCODE_SUCCESS != rc) {
throwExceptionHelper(currentThread, rc);
} else {
if (TrcEnabled_Trc_MODULE_addModulePackage) {
trcModulesAddModulePackage(currentThread, j9mod, package);
}
}
}
#if defined(CALL_BUNDLED_FUNCTIONS_DIRECTLY)
omrthread_monitor_exit(vm->classLoaderModuleAndLocationMutex);
#else
f_monitorExit(vm->classLoaderModuleAndLocationMutex);
#endif
vmFuncs->internalExitVMToJNI(currentThread);
}
#if JAVA_SPEC_VERSION >= 15
void JNICALL
JVM_AddModuleExportsToAllUnnamed(JNIEnv * env, jobject fromModule, jstring packageObj)
#else
void JNICALL
JVM_AddModuleExportsToAllUnnamed(JNIEnv * env, jobject fromModule, const char *package)
#endif
{
J9VMThread * const currentThread = (J9VMThread*)env;
J9JavaVM const * const vm = currentThread->javaVM;
J9InternalVMFunctions const * const vmFuncs = vm->internalVMFunctions;
#if JAVA_SPEC_VERSION >= 15
const char *package = NULL;
PORT_ACCESS_FROM_ENV(env);
#endif
vmFuncs->internalEnterVMFromJNI(currentThread);
#if defined(CALL_BUNDLED_FUNCTIONS_DIRECTLY)
omrthread_monitor_enter(vm->classLoaderModuleAndLocationMutex);
#else
f_monitorEnter(vm->classLoaderModuleAndLocationMutex);
#endif
#if JAVA_SPEC_VERSION >= 15
if (NULL != packageObj) {
j9object_t stringObject = J9_JNI_UNWRAP_REFERENCE(packageObj);
UDATA utfLength = vmFuncs->getStringUTF8Length(currentThread, stringObject) + 1;
char* packageName = (char *)j9mem_allocate_memory(utfLength, OMRMEM_CATEGORY_VM);
if (NULL == packageName) {
vmFuncs->setNativeOutOfMemoryError(currentThread, 0, 0);
goto done;
}
vmFuncs->copyStringToUTF8Helper(currentThread, stringObject, J9_STR_NULL_TERMINATE_RESULT | J9_STR_XLAT , 0, J9VMJAVALANGSTRING_LENGTH(currentThread, stringObject), (U_8 *)packageName, utfLength);
package = packageName;
} else {
vmFuncs->setCurrentExceptionNLS(currentThread, J9VMCONSTANTPOOL_JAVALANGNULLPOINTEREXCEPTION, J9NLS_VM_PACKAGE_IS_NULL);
goto done;
}
#endif
{
UDATA rc = ERRCODE_GENERAL_FAILURE;
J9Module * const j9FromMod = getJ9Module(currentThread, fromModule);
rc = exportPackageToAllUnamed(currentThread, j9FromMod, package);
if (ERRCODE_SUCCESS != rc) {
throwExceptionHelper(currentThread, rc);
}
}
#if JAVA_SPEC_VERSION >= 15
done:
if (NULL != package) {
j9mem_free_memory((void*)package);
}
#endif
#if defined(CALL_BUNDLED_FUNCTIONS_DIRECTLY)
omrthread_monitor_exit(vm->classLoaderModuleAndLocationMutex);
#else
f_monitorExit(vm->classLoaderModuleAndLocationMutex);
#endif
vmFuncs->internalExitVMToJNI(currentThread);
}
jstring JNICALL
JVM_GetSimpleBinaryName(JNIEnv *env, jclass arg1)
{
assert(!"JVM_GetSimpleBinaryName unimplemented");
return NULL;
}
void JNICALL
JVM_SetMethodInfo(JNIEnv *env, jobject arg1)
{
assert(!"JVM_SetMethodInfo unimplemented");
}
jint JNICALL
JVM_ConstantPoolGetNameAndTypeRefIndexAt(JNIEnv *env, jobject arg1, jobject arg2, jint arg3)
{
assert(!"JVM_ConstantPoolGetNameAndTypeRefIndexAt unimplemented");
return -1;
}
jint JNICALL
JVM_MoreStackWalk(JNIEnv *env, jobject arg1, jlong arg2, jlong arg3, jint arg4, jint arg5, jobjectArray arg6, jobjectArray arg7)
{
assert(!"JVM_MoreStackWalk unimplemented");
return -1;
}
jint JNICALL
JVM_ConstantPoolGetClassRefIndexAt(JNIEnv *env, jobject arg1, jlong arg2, jint arg3)
{
assert(!"JVM_ConstantPoolGetClassRefIndexAt unimplemented");
return -1;
}
jobjectArray JNICALL
JVM_GetVmArguments(JNIEnv *env)
{
J9VMThread* currentThread = (J9VMThread*)env;
J9JavaVM* vm = currentThread->javaVM;
J9InternalVMFunctions* internalFunctions = vm->internalVMFunctions;
jobjectArray result = NULL;
J9Class* vmClass = NULL;
internalFunctions->internalEnterVMFromJNI(currentThread);
vmClass = J9VMCOMIBMOTIVMVM_OR_NULL(vm);
if (NULL != vmClass) {
J9Method* method = internalFunctions->findJNIMethod(currentThread, vmClass, "getVMArgs", "()[Ljava/lang/String;");
if (NULL != method) {
jmethodID mid = (jmethodID)internalFunctions->getJNIMethodID(currentThread, method);
if (NULL != mid) {
jclass vmJniClass = (jclass)internalFunctions->j9jni_createLocalRef(env, vmClass->classObject);
if (NULL != vmJniClass) {
internalFunctions->internalExitVMToJNI(currentThread);
result = (jobjectArray)((*env)->CallObjectMethod(env, vmJniClass, mid));
internalFunctions->internalEnterVMFromJNI(currentThread);
internalFunctions->j9jni_deleteLocalRef(env, (jobject)vmJniClass);
goto success;
}
}
}
}
internalFunctions->setCurrentException(currentThread, J9VMCONSTANTPOOL_JAVALANGINTERNALERROR, NULL);
success:
internalFunctions->internalExitVMToJNI(currentThread);
return result;
}
void JNICALL
JVM_FillStackFrames(JNIEnv *env, jclass arg1, jint arg2, jobjectArray arg3, jint arg4, jint arg5)
{
assert(!"JVM_FillStackFrames unimplemented");
}
jclass JNICALL
JVM_FindClassFromCaller(JNIEnv* env, const char* arg1, jboolean arg2, jobject arg3, jclass arg4)
{
assert(!"JVM_FindClassFromCaller unimplemented");
return NULL;
}
jobjectArray JNICALL
JVM_ConstantPoolGetNameAndTypeRefInfoAt(JNIEnv *env, jobject arg1, jobject arg2, jint arg3)
{
assert(!"JVM_ConstantPoolGetNameAndTypeRefInfoAt unimplemented");
return NULL;
}
jbyte JNICALL
JVM_ConstantPoolGetTagAt(JNIEnv *env, jobject arg1, jobject arg2, jint arg3)
{
assert(!"JVM_ConstantPoolGetTagAt unimplemented");
return 0;
}
jobject JNICALL
JVM_CallStackWalk(JNIEnv *env, jobject arg1, jlong arg2, jint arg3, jint arg4, jint arg5, jobjectArray arg6, jobjectArray arg7)
{
assert(!"JVM_CallStackWalk unimplemented");
return NULL;
}
JNIEXPORT jobject JNICALL
JVM_GetAndClearReferencePendingList(JNIEnv *env)
{
assert(!"JVM_GetAndClearReferencePendingList unimplemented");
return NULL;
}
JNIEXPORT jboolean JNICALL
JVM_HasReferencePendingList(JNIEnv *env)
{
assert(!"JVM_HasReferencePendingList unimplemented");
return JNI_FALSE;
}
JNIEXPORT void JNICALL
JVM_WaitForReferencePendingList(JNIEnv *env)
{
assert(!"JVM_WaitForReferencePendingList unimplemented");
return;
}
void JNICALL
JVM_SetBootLoaderUnnamedModule(JNIEnv *env, jobject module)
{
J9VMThread * const currentThread = (J9VMThread*)env;
J9JavaVM * vm = currentThread->javaVM;
J9InternalVMFunctions const * const vmFuncs = vm->internalVMFunctions;
vmFuncs->internalEnterVMFromJNI(currentThread);
if (module == NULL) {
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGNULLPOINTEREXCEPTION, "module is null");
} else {
j9object_t modObj = J9_JNI_UNWRAP_REFERENCE(module);
J9ClassLoader *systemClassLoader = vm->systemClassLoader;
J9Class *instanceClazz = J9OBJECT_CLAZZ(currentThread, modObj);
if (!currentThread->currentException) {
J9Class *moduleClass = vmFuncs->internalFindKnownClass(currentThread,
J9VMCONSTANTPOOL_JAVALANGMODULE,
J9_FINDKNOWNCLASS_FLAG_INITIALIZE);
if (!isModuleUnnamed(currentThread, modObj)) {
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGILLEGALARGUMENTEXCEPTION, "named module was supplied");
} else if (!isSameOrSuperClassOf(moduleClass, instanceClazz)) {
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGILLEGALARGUMENTEXCEPTION, "module supplied is not same or sub class of java/lang/Module");
} else if (instanceClazz->classLoader != systemClassLoader) {
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGILLEGALARGUMENTEXCEPTION, "module was not loaded by the bootclassloader");
} else {
if (NULL == J9VMJAVALANGCLASSLOADER_UNNAMEDMODULE(currentThread, systemClassLoader->classLoaderObject)) {
J9Module *j9mod = createModule(currentThread, modObj, systemClassLoader, NULL );
J9VMJAVALANGCLASSLOADER_SET_UNNAMEDMODULE(currentThread, systemClassLoader->classLoaderObject, modObj);
Trc_MODULE_setBootloaderUnnamedModule(currentThread, j9mod);
} else {
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGINTERNALERROR, "module is already set in the bootclassloader");
}
}
}
}
vmFuncs->internalExitVMToJNI(currentThread);
}
void JNICALL
JVM_ToStackTraceElement(JNIEnv* env, jobject arg1, jobject arg2)
{
assert(!"JVM_ToStackTraceElement unimplemented");
}
void JNICALL
JVM_GetStackTraceElements(JNIEnv *env, jobject throwable, jobjectArray elements)
{
assert(!"JVM_GetStackTraceElements unimplemented");
}
void JNICALL
JVM_InitStackTraceElementArray(JNIEnv *env, jobjectArray elements, jobject throwable)
{
assert(!"JVM_InitStackTraceElementArray unimplemented");
}
void JNICALL
JVM_InitStackTraceElement(JNIEnv* env, jobject element, jobject stackFrameInfo)
{
assert(!"JVM_InitStackTraceElement unimplemented");
}
jobject JNICALL
JVM_GetModuleByPackageName(JNIEnv *env, jobject classLoader, jstring packageName)
{
J9VMThread * const currentThread = (J9VMThread*)env;
J9JavaVM * vm = currentThread->javaVM;
J9InternalVMFunctions const * const vmFuncs = vm->internalVMFunctions;
jobject module = NULL;
vmFuncs->internalEnterVMFromJNI(currentThread);
#if defined(CALL_BUNDLED_FUNCTIONS_DIRECTLY)
omrthread_monitor_enter(vm->classLoaderModuleAndLocationMutex);
#else
f_monitorEnter(vm->classLoaderModuleAndLocationMutex);
#endif
if (NULL == packageName) {
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGNULLPOINTEREXCEPTION, "package name is null");
} else {
J9ClassLoader *thisVMClassLoader = NULL;
J9UTF8 *packageUTF8 = NULL;
UDATA packageLength = 0;
char buf[J9VM_PACKAGE_NAME_BUFFER_LENGTH];
j9object_t packageObj = J9_JNI_UNWRAP_REFERENCE(packageName);
j9object_t moduleObj = NULL;
J9Module *vmModule = NULL;
PORT_ACCESS_FROM_VMC(currentThread);
if (NULL == classLoader) {
thisVMClassLoader = vm->systemClassLoader;
} else {
j9object_t thisClassloader = NULL;
J9Class *thisClassLoaderClass = NULL;
J9Class *classLoaderClass = vmFuncs->internalFindKnownClass(currentThread,
J9VMCONSTANTPOOL_JAVALANGCLASSLOADER,
J9_FINDKNOWNCLASS_FLAG_INITIALIZE
);
thisClassloader = J9_JNI_UNWRAP_REFERENCE(classLoader);
thisClassLoaderClass = J9OBJECT_CLAZZ(currentThread, thisClassloader);
if (!isSameOrSuperClassOf(classLoaderClass, thisClassLoaderClass)) {
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGILLEGALARGUMENTEXCEPTION, "classLoader is not same or subclass of java/lang/ClassLoader");
goto exit;
}
thisVMClassLoader = J9VMJAVALANGCLASSLOADER_VMREF(currentThread, thisClassloader);
}
packageUTF8 = vmFuncs->copyStringToJ9UTF8WithMemAlloc(currentThread, packageObj, J9_STR_NULL_TERMINATE_RESULT, "", 0, buf, J9VM_PACKAGE_NAME_BUFFER_LENGTH);
if (NULL == packageUTF8) {
vmFuncs->setNativeOutOfMemoryError(currentThread, 0, 0);
goto exit;
}
if (NULL != strchr((const char*)J9UTF8_DATA(packageUTF8), '.')) {
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGILLEGALARGUMENTEXCEPTION, "package name contains '.' instead of '/'");
} else {
if (vmFuncs->isAnyClassLoadedFromPackage(thisVMClassLoader, J9UTF8_DATA(packageUTF8), J9UTF8_LENGTH(packageUTF8))) {
vmModule = vmFuncs->findModuleForPackageUTF8(currentThread, thisVMClassLoader, packageUTF8);
if (NULL == vmModule) {
moduleObj = J9VMJAVALANGCLASSLOADER_UNNAMEDMODULE(currentThread, thisVMClassLoader->classLoaderObject);
} else {
moduleObj = vmModule->moduleObject;
}
module = vmFuncs->j9jni_createLocalRef((JNIEnv *) currentThread, moduleObj);
if (NULL == module) {
vmFuncs->setNativeOutOfMemoryError(currentThread, 0, 0);
}
}
}
if (packageUTF8 != (J9UTF8*)buf) {
j9mem_free_memory(packageUTF8);
}
}
exit:
#if defined(CALL_BUNDLED_FUNCTIONS_DIRECTLY)
omrthread_monitor_exit(vm->classLoaderModuleAndLocationMutex);
#else
f_monitorExit(vm->classLoaderModuleAndLocationMutex);
#endif
vmFuncs->internalExitVMToJNI(currentThread);
return module;
}
jlong JNICALL
JVM_GetNanoTimeAdjustment(JNIEnv *env, jclass clazz, jlong offsetSeconds)
{
PORT_ACCESS_FROM_ENV(env);
jlong offsetNanoSeconds = 0;
jlong currentTimeNano = 0;
jlong result = -1;
if ((offsetSeconds <= OFFSET_MAX) && (offsetSeconds >= OFFSET_MIN)) {
UDATA success = 0;
offsetNanoSeconds = offsetSeconds * J9TIME_NANOSECONDS_PER_SECOND;
currentTimeNano = (jlong) j9time_current_time_nanos(&success);
if (success) {
if ((offsetNanoSeconds >= (currentTimeNano - TIME_LONG_MAX))
&& (offsetNanoSeconds <= (currentTimeNano - TIME_LONG_MIN))
) {
result = currentTimeNano - offsetNanoSeconds;
}
}
}
return result;
}
JNIEXPORT jclass JNICALL
JVM_GetNestHost(JNIEnv *env, jclass clz)
{
assert(!"JVM_GetNestHost unimplemented");
return NULL;
}
JNIEXPORT jobjectArray JNICALL
JVM_GetNestMembers(JNIEnv *env, jclass clz)
{
assert(!"JVM_GetNestMembers unimplemented");
return NULL;
}
JNIEXPORT jboolean JNICALL
JVM_AreNestMates(JNIEnv *env, jclass jClassOne, jclass jClassTwo)
{
jboolean result = JNI_FALSE;
if ((NULL != jClassOne) && (NULL != jClassTwo)) {
j9object_t clazzObjectOne = NULL;
j9object_t clazzObjectTwo = NULL;
J9VMThread *currentThread = (J9VMThread*)env;
J9InternalVMFunctions *vmFuncs = currentThread->javaVM->internalVMFunctions;
vmFuncs->internalEnterVMFromJNI(currentThread);
clazzObjectOne = J9_JNI_UNWRAP_REFERENCE(jClassOne);
clazzObjectTwo = J9_JNI_UNWRAP_REFERENCE(jClassTwo);
if (clazzObjectOne == clazzObjectTwo) {
result = JNI_TRUE;
} else {
J9Class *clazzOne = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, clazzObjectOne);
J9Class *clazzTwo = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, clazzObjectTwo);
if (NULL == clazzOne->nestHost) {
if (J9_VISIBILITY_ALLOWED != vmFuncs->loadAndVerifyNestHost(currentThread, clazzOne, J9_LOOK_NO_THROW)) {
goto done;
}
}
if (NULL == clazzTwo->nestHost) {
if (J9_VISIBILITY_ALLOWED != vmFuncs->loadAndVerifyNestHost(currentThread, clazzTwo, J9_LOOK_NO_THROW)) {
goto done;
}
}
if (clazzOne->nestHost == clazzTwo->nestHost) {
result = JNI_TRUE;
}
}
done:
vmFuncs->internalExitVMToJNI(currentThread);
}
return result;
}
#endif
#if JAVA_SPEC_VERSION >= 15
JNIEXPORT void JNICALL
JVM_RegisterLambdaProxyClassForArchiving(JNIEnv *env, jclass arg1, jstring arg2, jobject arg3, jobject arg4, jobject arg5, jobject arg6, jclass arg7)
{
assert(!"JVM_RegisterLambdaProxyClassForArchiving unimplemented");
}
JNIEXPORT jclass JNICALL
JVM_LookupLambdaProxyClassFromArchive(JNIEnv *env, jclass arg1, jstring arg2, jobject arg3, jobject arg4, jobject arg5, jobject arg6
#if JAVA_SPEC_VERSION == 15
, jboolean arg7
#endif
)
{
assert(!"JVM_LookupLambdaProxyClassFromArchive unimplemented");
return NULL;
}
JNIEXPORT jboolean JNICALL
JVM_IsCDSDumpingEnabled(JNIEnv *env)
{
return JNI_FALSE;
}
#endif
#if JAVA_SPEC_VERSION >= 16
JNIEXPORT jlong JNICALL
JVM_GetRandomSeedForDumping()
{
return 0;
}
JNIEXPORT jboolean JNICALL
JVM_IsSharingEnabled(JNIEnv *env)
{
return JNI_FALSE;
}
#endif
JNIEXPORT jboolean JNICALL
JVM_IsUseContainerSupport(JNIEnv *env)
{
PORT_ACCESS_FROM_ENV(env);
OMRPORT_ACCESS_FROM_J9PORT(PORTLIB);
BOOLEAN inContainer = omrsysinfo_is_running_in_container();
return inContainer ? JNI_TRUE : JNI_FALSE;
}