# HG changeset patch # User redestad # Date 1483634109 -3600 # Thu Jan 05 17:35:09 2017 +0100 # Node ID 64068f2bd47dfdb1d696aca86e0e0d244721e18c # Parent 0521bec3379f7fcafd14c4fe6b176e34b46dcd34 8171855: Move package name transformations during module bootstrap into native code Reviewed-by: alanb, acorn, lfoltan, mchung diff --git a/src/java.base/share/classes/java/lang/reflect/Module.java b/src/java.base/share/classes/java/lang/reflect/Module.java --- a/src/java.base/share/classes/java/lang/reflect/Module.java +++ b/src/java.base/share/classes/java/lang/reflect/Module.java @@ -128,14 +128,8 @@ Version version = descriptor.version().orElse(null); String vs = Objects.toString(version, null); String loc = Objects.toString(uri, null); - Set packages = descriptor.packages(); - int n = packages.size(); - String[] array = new String[n]; - int i = 0; - for (String pn : packages) { - array[i++] = pn.replace('.', '/'); - } - defineModule0(this, isOpen, vs, loc, array); + String[] packages = descriptor.packages().toArray(new String[0]); + defineModule0(this, isOpen, vs, loc, packages); } @@ -789,13 +783,12 @@ // update VM first, just in case it fails if (syncVM) { - String pkgInternalForm = pn.replace('.', '/'); if (other == EVERYONE_MODULE) { - addExportsToAll0(this, pkgInternalForm); + addExportsToAll0(this, pn); } else if (other == ALL_UNNAMED_MODULE) { - addExportsToAllUnnamed0(this, pkgInternalForm); + addExportsToAllUnnamed0(this, pn); } else { - addExports0(this, pkgInternalForm, other); + addExports0(this, pn, other); } } @@ -1021,7 +1014,7 @@ // update VM first, just in case it fails if (syncVM) - addPackage0(this, pn.replace('.', '/')); + addPackage0(this, pn); // replace with new set this.extraPackages = extraPackages; // volatile write @@ -1180,8 +1173,7 @@ if (descriptor.isOpen()) { assert descriptor.opens().isEmpty(); for (String source : descriptor.packages()) { - String sourceInternalForm = source.replace('.', '/'); - addExportsToAll0(m, sourceInternalForm); + addExportsToAll0(m, source); } return; } @@ -1192,7 +1184,6 @@ // process the open packages first for (Opens opens : descriptor.opens()) { String source = opens.source(); - String sourceInternalForm = source.replace('.', '/'); if (opens.isQualified()) { // qualified opens @@ -1201,7 +1192,7 @@ // only open to modules that are in this configuration Module m2 = nameToModule.get(target); if (m2 != null) { - addExports0(m, sourceInternalForm, m2); + addExports0(m, source, m2); targets.add(m2); } } @@ -1210,7 +1201,7 @@ } } else { // unqualified opens - addExportsToAll0(m, sourceInternalForm); + addExportsToAll0(m, source); openPackages.put(source, EVERYONE_SET); } } @@ -1218,7 +1209,6 @@ // next the exports, skipping exports when the package is open for (Exports exports : descriptor.exports()) { String source = exports.source(); - String sourceInternalForm = source.replace('.', '/'); // skip export if package is already open to everyone Set openToTargets = openPackages.get(source); @@ -1234,7 +1224,7 @@ if (m2 != null) { // skip qualified export if already open to m2 if (openToTargets == null || !openToTargets.contains(m2)) { - addExports0(m, sourceInternalForm, m2); + addExports0(m, source, m2); targets.add(m2); } } @@ -1245,7 +1235,7 @@ } else { // unqualified exports - addExportsToAll0(m, sourceInternalForm); + addExportsToAll0(m, source); exportedPackages.put(source, EVERYONE_SET); } } diff --git a/src/java.base/share/native/include/jvm.h b/src/java.base/share/native/include/jvm.h --- a/src/java.base/share/native/include/jvm.h +++ b/src/java.base/share/native/include/jvm.h @@ -403,7 +403,7 @@ JNIEXPORT void JNICALL JVM_DefineModule(JNIEnv *env, jobject module, jboolean is_open, jstring version, - jstring location, jobjectArray packages); + jstring location, const char* const* packages, jsize num_packages); JNIEXPORT void JNICALL JVM_SetBootLoaderUnnamedModule(JNIEnv *env, jobject module); @@ -412,19 +412,16 @@ JVM_AddReadsModule(JNIEnv *env, jobject from_module, jobject to_module); JNIEXPORT void JNICALL -JVM_AddModuleExports(JNIEnv *env, jobject from_module, jstring package, jobject to_module); +JVM_AddModuleExports(JNIEnv *env, jobject from_module, const char* package, jobject to_module); JNIEXPORT void JNICALL -JVM_AddModuleExportsToAll(JNIEnv *env, jobject from_module, jstring package); +JVM_AddModuleExportsToAll(JNIEnv *env, jobject from_module, const char* package); JNIEXPORT void JNICALL -JVM_AddModuleExportsToAllUnnamed(JNIEnv *env, jobject from_module, jstring package); +JVM_AddModuleExportsToAllUnnamed(JNIEnv *env, jobject from_module, const char* package); JNIEXPORT void JNICALL -JVM_AddModulePackage(JNIEnv* env, jobject module, jstring package); - -JNIEXPORT jobject JNICALL -JVM_GetModuleByPackageName(JNIEnv *env, jobject cl, jstring pkg); +JVM_AddModulePackage(JNIEnv* env, jobject module, const char* package); /* * Reflection support functions diff --git a/src/java.base/share/native/libjava/Module.c b/src/java.base/share/native/libjava/Module.c --- a/src/java.base/share/native/libjava/Module.c +++ b/src/java.base/share/native/libjava/Module.c @@ -22,18 +22,73 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ +#include +#include #include "jni.h" +#include "jni_util.h" #include "jvm.h" #include "java_lang_reflect_Module.h" +/* + * Translates '.' to '/'. Does no validation, assumption being that both + * calling code in java.lang.reflect.Module and VM will do deeper validation. + */ +JNIEXPORT void +ToInternalForm(char *name) +{ + char *p = name; + while (*p != '\0') { + if (*p == '.') { + *p = '/'; + } + p++; + } +} + JNIEXPORT void JNICALL Java_java_lang_reflect_Module_defineModule0(JNIEnv *env, jclass cls, jobject module, jboolean is_open, jstring version, jstring location, jobjectArray packages) { - JVM_DefineModule(env, module, is_open, version, location, packages); + char** pkgs = NULL; + jsize idx; + jsize pkgs_len = (*env)->GetArrayLength(env, packages); + + if (pkgs_len != 0 && (pkgs = calloc(pkgs_len, sizeof(char*))) == NULL) { + JNU_ThrowOutOfMemoryError(env, NULL); + return; + } else { + int valid = 1; + for (idx = 0; idx < pkgs_len; idx++) { + jstring pkg = (*env)->GetObjectArrayElement(env, packages, idx); + jsize len = (*env)->GetStringUTFLength(env, pkg); + jsize unicode_len = (*env)->GetStringLength(env, pkg); + + pkgs[idx] = malloc(len + 1); + if (pkgs[idx] == NULL) { + JNU_ThrowOutOfMemoryError(env, NULL); + valid = 0; + break; + } + + (*env)->GetStringUTFRegion(env, pkg, 0, unicode_len, pkgs[idx]); + ToInternalForm(pkgs[idx]); + } + + if (valid != 0) { + JVM_DefineModule(env, module, is_open, version, location, + (const char* const*)pkgs, pkgs_len); + } + } + + for (idx = 0; idx < pkgs_len; idx++) { + if (pkgs[idx] != NULL) { + free(pkgs[idx]); + } + } + free(pkgs); } JNIEXPORT void JNICALL @@ -46,25 +101,101 @@ Java_java_lang_reflect_Module_addExports0(JNIEnv *env, jclass cls, jobject from, jstring pkg, jobject to) { - JVM_AddModuleExports(env, from, pkg, to); + jsize len; + jsize unicode_len; + char* pkg_name; + + if (pkg == NULL) { + JNU_ThrowNullPointerException(env, "package is null"); + return; + } + + len = (*env)->GetStringUTFLength(env, pkg); + unicode_len = (*env)->GetStringLength(env, pkg); + pkg_name = malloc(len + 1); + if (pkg_name == NULL) { + JNU_ThrowOutOfMemoryError(env, NULL); + } else { + (*env)->GetStringUTFRegion(env, pkg, 0, unicode_len, pkg_name); + ToInternalForm(pkg_name); + JVM_AddModuleExports(env, from, pkg_name, to); + free(pkg_name); + } } JNIEXPORT void JNICALL Java_java_lang_reflect_Module_addExportsToAll0(JNIEnv *env, jclass cls, jobject from, jstring pkg) { - JVM_AddModuleExportsToAll(env, from, pkg); + jsize len; + jsize unicode_len; + char* pkg_name; + + if (pkg == NULL) { + JNU_ThrowNullPointerException(env, "package is null"); + return; + } + + len = (*env)->GetStringUTFLength(env, pkg); + unicode_len = (*env)->GetStringLength(env, pkg); + pkg_name = malloc(len + 1); + if (pkg_name == NULL) { + JNU_ThrowOutOfMemoryError(env, NULL); + } else { + (*env)->GetStringUTFRegion(env, pkg, 0, unicode_len, pkg_name); + ToInternalForm(pkg_name); + JVM_AddModuleExportsToAll(env, from, pkg_name); + free(pkg_name); + } } JNIEXPORT void JNICALL Java_java_lang_reflect_Module_addExportsToAllUnnamed0(JNIEnv *env, jclass cls, jobject from, jstring pkg) { - JVM_AddModuleExportsToAllUnnamed(env, from, pkg); + jsize len; + jsize unicode_len; + char* pkg_name; + + if (pkg == NULL) { + JNU_ThrowNullPointerException(env, "package is null"); + return; + } + + len = (*env)->GetStringUTFLength(env, pkg); + unicode_len = (*env)->GetStringLength(env, pkg); + pkg_name = malloc(len + 1); + if (pkg_name == NULL) { + JNU_ThrowOutOfMemoryError(env, NULL); + } else { + (*env)->GetStringUTFRegion(env, pkg, 0, unicode_len, pkg_name); + ToInternalForm(pkg_name); + JVM_AddModuleExportsToAllUnnamed(env, from, pkg_name); + free(pkg_name); + } } JNIEXPORT void JNICALL Java_java_lang_reflect_Module_addPackage0(JNIEnv *env, jclass cls, jobject m, jstring pkg) { - JVM_AddModulePackage(env, m, pkg); + jsize len; + jsize unicode_len; + char* pkg_name; + + if (pkg == NULL) { + JNU_ThrowNullPointerException(env, "package is null"); + return; + } + + len = (*env)->GetStringUTFLength(env, pkg); + unicode_len = (*env)->GetStringLength(env, pkg); + pkg_name = malloc(len + 1); + if (pkg_name == NULL) { + JNU_ThrowOutOfMemoryError(env, NULL); + } else { + (*env)->GetStringUTFRegion(env, pkg, 0, unicode_len, pkg_name); + ToInternalForm(pkg_name); + JVM_AddModulePackage(env, m, pkg_name); + free(pkg_name); + } }