annotate hotspot/src/share/vm/classfile/modules.cpp @ 46463:4bd2ca84df7a

8178604: JVM does not allow defining boot loader modules in exploded build after module system initialization Summary: Allow defining of boot loader modules after initialization but add locks to synchronize access to exploded build list Reviewed-by: dholmes, lfoltan
author hseigel
date Tue, 16 May 2017 09:33:49 -0400
parents 3c12af929e7d
children 388aa8d67c80
rev   line source
alanb@36508 1 /*
hseigel@43471 2 * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
alanb@36508 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
alanb@36508 4 *
alanb@36508 5 * This code is free software; you can redistribute it and/or modify it
alanb@36508 6 * under the terms of the GNU General Public License version 2 only, as
alanb@36508 7 * published by the Free Software Foundation.
alanb@36508 8 *
alanb@36508 9 * This code is distributed in the hope that it will be useful, but WITHOUT
alanb@36508 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
alanb@36508 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
alanb@36508 12 * version 2 for more details (a copy is included in the LICENSE file that
alanb@36508 13 * accompanied this code).
alanb@36508 14 *
alanb@36508 15 * You should have received a copy of the GNU General Public License version
alanb@36508 16 * 2 along with this work; if not, write to the Free Software Foundation,
alanb@36508 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
alanb@36508 18 *
alanb@36508 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
alanb@36508 20 * or visit www.oracle.com if you need additional information or have any
alanb@36508 21 * questions.
alanb@36508 22 *
alanb@36508 23 */
alanb@36508 24
alanb@36508 25 #include "precompiled.hpp"
alanb@36508 26 #include "classfile/classFileParser.hpp"
alanb@36508 27 #include "classfile/classLoader.hpp"
alanb@36508 28 #include "classfile/classLoaderData.inline.hpp"
alanb@36508 29 #include "classfile/javaAssertions.hpp"
alanb@36508 30 #include "classfile/javaClasses.hpp"
alanb@36508 31 #include "classfile/javaClasses.inline.hpp"
alanb@36508 32 #include "classfile/moduleEntry.hpp"
alanb@36508 33 #include "classfile/modules.hpp"
alanb@36508 34 #include "classfile/packageEntry.hpp"
alanb@36508 35 #include "classfile/stringTable.hpp"
alanb@36508 36 #include "classfile/symbolTable.hpp"
alanb@42307 37 #include "classfile/systemDictionary.hpp"
alanb@36508 38 #include "classfile/vmSymbols.hpp"
alanb@36508 39 #include "logging/log.hpp"
jprovino@37248 40 #include "memory/resourceArea.hpp"
alanb@36508 41 #include "oops/instanceKlass.hpp"
alanb@36508 42 #include "runtime/arguments.hpp"
alanb@36508 43 #include "runtime/handles.inline.hpp"
alanb@36508 44 #include "runtime/javaCalls.hpp"
alanb@36508 45 #include "runtime/reflection.hpp"
alanb@42307 46 #include "utilities/stringUtils.hpp"
alanb@36508 47 #include "utilities/utf8.hpp"
alanb@36508 48
redestad@43466 49 static bool verify_module_name(const char *module_name) {
alanb@36508 50 if (module_name == NULL) return false;
alanb@36508 51 int len = (int)strlen(module_name);
alanb@42630 52 return (len > 0 && len <= Symbol::max_length());
alanb@36508 53 }
alanb@36508 54
redestad@43466 55 bool Modules::verify_package_name(const char* package_name) {
alanb@36508 56 if (package_name == NULL) return false;
alanb@36508 57 int len = (int)strlen(package_name);
alanb@36508 58 return (len > 0 && len <= Symbol::max_length() &&
redestad@43466 59 UTF8::is_legal_utf8((const unsigned char *)package_name, len, false) &&
alanb@36508 60 ClassFileParser::verify_unqualified_name(package_name, len,
alanb@36508 61 ClassFileParser::LegalClass));
alanb@36508 62 }
alanb@36508 63
alanb@36508 64 static char* get_module_name(oop module, TRAPS) {
alanb@44520 65 oop name_oop = java_lang_Module::name(module);
alanb@36508 66 if (name_oop == NULL) {
alanb@36508 67 THROW_MSG_NULL(vmSymbols::java_lang_NullPointerException(), "Null module name");
alanb@36508 68 }
alanb@36508 69 char* module_name = java_lang_String::as_utf8_string(name_oop);
alanb@36508 70 if (!verify_module_name(module_name)) {
alanb@36508 71 THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(),
alanb@36508 72 err_msg("Invalid module name: %s",
alanb@36508 73 module_name != NULL ? module_name : "NULL"));
alanb@36508 74 }
alanb@36508 75 return module_name;
alanb@36508 76 }
alanb@36508 77
alanb@36508 78 static const char* get_module_version(jstring version) {
alanb@36508 79 if (version == NULL) {
alanb@36508 80 return NULL;
alanb@36508 81 }
alanb@36508 82 return java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(version));
alanb@36508 83 }
alanb@36508 84
alanb@36508 85 static ModuleEntryTable* get_module_entry_table(Handle h_loader, TRAPS) {
alanb@36508 86 // This code can be called during start-up, before the classLoader's classLoader data got
alanb@36508 87 // created. So, call register_loader() to make sure the classLoader data gets created.
alanb@36508 88 ClassLoaderData *loader_cld = SystemDictionary::register_loader(h_loader, CHECK_NULL);
alanb@36508 89 return loader_cld->modules();
alanb@36508 90 }
alanb@36508 91
alanb@36508 92 static PackageEntryTable* get_package_entry_table(Handle h_loader, TRAPS) {
alanb@36508 93 // This code can be called during start-up, before the classLoader's classLoader data got
alanb@36508 94 // created. So, call register_loader() to make sure the classLoader data gets created.
alanb@36508 95 ClassLoaderData *loader_cld = SystemDictionary::register_loader(h_loader, CHECK_NULL);
alanb@36508 96 return loader_cld->packages();
alanb@36508 97 }
alanb@36508 98
alanb@36508 99 static ModuleEntry* get_module_entry(jobject module, TRAPS) {
alanb@36508 100 Handle module_h(THREAD, JNIHandles::resolve(module));
alanb@44520 101 if (!java_lang_Module::is_instance(module_h())) {
lfoltan@40020 102 THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(),
alanb@44520 103 "module is not an instance of type java.lang.Module");
alanb@36508 104 }
alanb@44520 105 return java_lang_Module::module_entry(module_h(), CHECK_NULL);
alanb@36508 106 }
alanb@36508 107
redestad@43466 108 static PackageEntry* get_package_entry(ModuleEntry* module_entry, const char* package_name, TRAPS) {
alanb@36508 109 ResourceMark rm(THREAD);
alanb@36508 110 if (package_name == NULL) return NULL;
alanb@36508 111 TempNewSymbol pkg_symbol = SymbolTable::new_symbol(package_name, CHECK_NULL);
lfoltan@39616 112 PackageEntryTable* package_entry_table = module_entry->loader_data()->packages();
alanb@36508 113 assert(package_entry_table != NULL, "Unexpected null package entry table");
alanb@36508 114 return package_entry_table->lookup_only(pkg_symbol);
alanb@36508 115 }
alanb@36508 116
alanb@36508 117 static PackageEntry* get_package_entry_by_name(Symbol* package,
alanb@36508 118 Handle h_loader,
alanb@36508 119 TRAPS) {
alanb@36508 120 if (package != NULL) {
alanb@36508 121 ResourceMark rm(THREAD);
alanb@36508 122 if (Modules::verify_package_name(package->as_C_string())) {
alanb@36508 123 PackageEntryTable* const package_entry_table =
alanb@36508 124 get_package_entry_table(h_loader, CHECK_NULL);
alanb@36508 125 assert(package_entry_table != NULL, "Unexpected null package entry table");
alanb@36508 126 return package_entry_table->lookup_only(package);
alanb@36508 127 }
alanb@36508 128 }
alanb@36508 129 return NULL;
alanb@36508 130 }
alanb@36508 131
alanb@36508 132 bool Modules::is_package_defined(Symbol* package, Handle h_loader, TRAPS) {
alanb@36508 133 PackageEntry* res = get_package_entry_by_name(package, h_loader, CHECK_false);
alanb@36508 134 return res != NULL;
alanb@36508 135 }
alanb@36508 136
alanb@36508 137 static void define_javabase_module(jobject module, jstring version,
redestad@43466 138 jstring location, const char* const* packages,
redestad@43466 139 jsize num_packages, TRAPS) {
alanb@36508 140 ResourceMark rm(THREAD);
alanb@36508 141
alanb@36508 142 Handle module_handle(THREAD, JNIHandles::resolve(module));
alanb@36508 143
alanb@36508 144 // Obtain java.base's module version
alanb@36508 145 const char* module_version = get_module_version(version);
alanb@36508 146 TempNewSymbol version_symbol;
alanb@36508 147 if (module_version != NULL) {
alanb@36508 148 version_symbol = SymbolTable::new_symbol(module_version, CHECK);
alanb@36508 149 } else {
alanb@36508 150 version_symbol = NULL;
alanb@36508 151 }
alanb@36508 152
alanb@36508 153 // Obtain java.base's location
alanb@36508 154 const char* module_location = NULL;
alanb@36508 155 TempNewSymbol location_symbol = NULL;
alanb@36508 156 if (location != NULL) {
alanb@36508 157 module_location =
alanb@36508 158 java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(location));
alanb@36508 159 if (module_location != NULL) {
alanb@36508 160 location_symbol = SymbolTable::new_symbol(module_location, CHECK);
alanb@36508 161 }
alanb@36508 162 }
alanb@36508 163
alanb@36508 164
hseigel@46322 165 // Check that the packages are syntactically ok.
alanb@36508 166 GrowableArray<Symbol*>* pkg_list = new GrowableArray<Symbol*>(num_packages);
alanb@36508 167 for (int x = 0; x < num_packages; x++) {
redestad@43466 168 const char *package_name = packages[x];
alanb@36508 169 if (!Modules::verify_package_name(package_name)) {
alanb@36508 170 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
rprotacio@42636 171 err_msg("Invalid package name: %s for module: " JAVA_BASE_NAME, package_name));
alanb@36508 172 }
alanb@36508 173 Symbol* pkg_symbol = SymbolTable::new_symbol(package_name, CHECK);
hseigel@46322 174 pkg_list->append(pkg_symbol);
alanb@36508 175 }
alanb@36508 176
alanb@36508 177 // Validate java_base's loader is the boot loader.
alanb@44520 178 oop loader = java_lang_Module::loader(module_handle());
alanb@36508 179 if (loader != NULL) {
alanb@36508 180 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
alanb@36508 181 "Class loader must be the boot class loader");
alanb@36508 182 }
coleenp@46271 183 Handle h_loader(THREAD, loader);
alanb@36508 184
alanb@36508 185 // Ensure the boot loader's PackageEntryTable has been created
alanb@36508 186 PackageEntryTable* package_table = get_package_entry_table(h_loader, CHECK);
alanb@36508 187 assert(pkg_list->length() == 0 || package_table != NULL, "Bad package_table");
alanb@36508 188
alanb@36508 189 // Ensure java.base's ModuleEntry has been created
rprotacio@42636 190 assert(ModuleEntryTable::javabase_moduleEntry() != NULL, "No ModuleEntry for " JAVA_BASE_NAME);
alanb@36508 191
hseigel@38732 192 bool duplicate_javabase = false;
alanb@36508 193 {
alanb@36508 194 MutexLocker m1(Module_lock, THREAD);
alanb@36508 195
lfoltan@38014 196 if (ModuleEntryTable::javabase_defined()) {
hseigel@38732 197 duplicate_javabase = true;
hseigel@38732 198 } else {
hseigel@38732 199
hseigel@38732 200 // Verify that all java.base packages created during bootstrapping are in
hseigel@38732 201 // pkg_list. If any are not in pkg_list, than a non-java.base class was
hseigel@38732 202 // loaded erroneously pre java.base module definition.
hseigel@38732 203 package_table->verify_javabase_packages(pkg_list);
hseigel@38732 204
hseigel@38732 205 // loop through and add any new packages for java.base
hseigel@38732 206 PackageEntry* pkg;
hseigel@38732 207 for (int x = 0; x < pkg_list->length(); x++) {
hseigel@38732 208 // Some of java.base's packages were added early in bootstrapping, ignore duplicates.
hseigel@38732 209 if (package_table->lookup_only(pkg_list->at(x)) == NULL) {
lfoltan@41183 210 pkg = package_table->locked_create_entry_or_null(pkg_list->at(x), ModuleEntryTable::javabase_moduleEntry());
rprotacio@42636 211 assert(pkg != NULL, "Unable to create a " JAVA_BASE_NAME " package entry");
hseigel@38732 212 }
hseigel@38732 213 // Unable to have a GrowableArray of TempNewSymbol. Must decrement the refcount of
hseigel@38732 214 // the Symbol* that was created above for each package. The refcount was incremented
hseigel@38732 215 // by SymbolTable::new_symbol and as well by the PackageEntry creation.
hseigel@38732 216 pkg_list->at(x)->decrement_refcount();
hseigel@38732 217 }
hseigel@38732 218
hseigel@38732 219 // Finish defining java.base's ModuleEntry
hseigel@38732 220 ModuleEntryTable::finalize_javabase(module_handle, version_symbol, location_symbol);
lfoltan@38014 221 }
hseigel@38732 222 }
hseigel@38732 223 if (duplicate_javabase) {
hseigel@43446 224 THROW_MSG(vmSymbols::java_lang_InternalError(),
rprotacio@42636 225 "Module " JAVA_BASE_NAME " is already defined");
alanb@36508 226 }
alanb@36508 227
hseigel@41691 228 // Only the thread that actually defined the base module will get here,
hseigel@41691 229 // so no locking is needed.
hseigel@41691 230
alanb@44520 231 // Patch any previously loaded class's module field with java.base's java.lang.Module.
hseigel@41691 232 ModuleEntryTable::patch_javabase_entries(module_handle);
hseigel@41691 233
alanb@44993 234 log_info(module, load)(JAVA_BASE_NAME " location: %s",
alanb@44993 235 module_location != NULL ? module_location : "NULL");
alanb@44993 236 log_debug(module)("define_javabase_module(): Definition of module: "
alanb@44993 237 JAVA_BASE_NAME ", version: %s, location: %s, package #: %d",
alanb@44993 238 module_version != NULL ? module_version : "NULL",
alanb@44993 239 module_location != NULL ? module_location : "NULL",
alanb@44993 240 pkg_list->length());
alanb@36508 241
alanb@36508 242 // packages defined to java.base
kvn@46458 243 if (log_is_enabled(Trace, module)) {
rprotacio@46404 244 for (int x = 0; x < pkg_list->length(); x++) {
kvn@46458 245 log_trace(module)("define_javabase_module(): creation of package %s for module " JAVA_BASE_NAME,
kvn@46458 246 (pkg_list->at(x))->as_C_string());
rprotacio@46404 247 }
alanb@36508 248 }
alanb@36508 249 }
alanb@36508 250
hseigel@43446 251 // Caller needs ResourceMark.
hseigel@43446 252 void throw_dup_pkg_exception(const char* module_name, PackageEntry* package, TRAPS) {
hseigel@43446 253 const char* package_name = package->name()->as_C_string();
hseigel@43446 254 if (package->module()->is_named()) {
hseigel@43446 255 THROW_MSG(vmSymbols::java_lang_IllegalStateException(),
hseigel@43446 256 err_msg("Package %s for module %s is already in another module, %s, defined to the class loader",
hseigel@43446 257 package_name, module_name, package->module()->name()->as_C_string()));
hseigel@43446 258 } else {
hseigel@43446 259 THROW_MSG(vmSymbols::java_lang_IllegalStateException(),
hseigel@43446 260 err_msg("Package %s for module %s is already in the unnamed module defined to the class loader",
hseigel@43446 261 package_name, module_name));
hseigel@43446 262 }
hseigel@43446 263 }
hseigel@43446 264
rprotacio@46404 265 void Modules::define_module(jobject module, jboolean is_open, jstring version,
redestad@43466 266 jstring location, const char* const* packages,
redestad@43466 267 jsize num_packages, TRAPS) {
alanb@36508 268 ResourceMark rm(THREAD);
alanb@36508 269
alanb@36508 270 if (module == NULL) {
alanb@36508 271 THROW_MSG(vmSymbols::java_lang_NullPointerException(), "Null module object");
alanb@36508 272 }
redestad@43466 273
redestad@43466 274 if (num_packages < 0) {
redestad@43466 275 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
redestad@43466 276 "num_packages must be >= 0");
redestad@43466 277 }
redestad@43466 278
redestad@43466 279 if (packages == NULL && num_packages > 0) {
redestad@43466 280 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
redestad@43466 281 "num_packages should be zero if packages is null");
redestad@43466 282 }
redestad@43466 283
alanb@36508 284 Handle module_handle(THREAD, JNIHandles::resolve(module));
alanb@44520 285 if (!java_lang_Module::is_instance(module_handle())) {
alanb@36508 286 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
alanb@44520 287 "module is not an instance of type java.lang.Module");
alanb@36508 288 }
alanb@36508 289
alanb@36508 290 char* module_name = get_module_name(module_handle(), CHECK);
alanb@36508 291 if (module_name == NULL) {
alanb@36508 292 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
alanb@36508 293 "Module name cannot be null");
alanb@36508 294 }
alanb@36508 295
alanb@36508 296 // Special handling of java.base definition
rprotacio@42636 297 if (strcmp(module_name, JAVA_BASE_NAME) == 0) {
rprotacio@46404 298 assert(is_open == JNI_FALSE, "java.base module cannot be open");
redestad@43466 299 define_javabase_module(module, version, location, packages, num_packages, CHECK);
alanb@36508 300 return;
alanb@36508 301 }
alanb@36508 302
alanb@36508 303 const char* module_version = get_module_version(version);
alanb@36508 304
alanb@44520 305 oop loader = java_lang_Module::loader(module_handle());
alanb@42307 306 // Make sure loader is not the jdk.internal.reflect.DelegatingClassLoader.
alanb@42307 307 if (loader != java_lang_ClassLoader::non_reflection_class_loader(loader)) {
alanb@42307 308 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
alanb@42307 309 "Class loader is an invalid delegating class loader");
alanb@42307 310 }
alanb@42307 311 Handle h_loader = Handle(THREAD, loader);
alanb@42307 312
alanb@36508 313 // Check that the list of packages has no duplicates and that the
alanb@36508 314 // packages are syntactically ok.
alanb@36508 315 GrowableArray<Symbol*>* pkg_list = new GrowableArray<Symbol*>(num_packages);
alanb@36508 316 for (int x = 0; x < num_packages; x++) {
redestad@43466 317 const char* package_name = packages[x];
alanb@36508 318 if (!verify_package_name(package_name)) {
alanb@36508 319 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
alanb@36508 320 err_msg("Invalid package name: %s for module: %s",
alanb@36508 321 package_name, module_name));
alanb@36508 322 }
alanb@42307 323
alanb@42307 324 // Only modules defined to either the boot or platform class loader, can define a "java/" package.
alanb@42307 325 if (!h_loader.is_null() &&
coleenp@46271 326 !SystemDictionary::is_platform_class_loader(h_loader()) &&
alanb@44326 327 (strncmp(package_name, JAVAPKG, JAVAPKG_LEN) == 0 &&
alanb@44326 328 (package_name[JAVAPKG_LEN] == '/' || package_name[JAVAPKG_LEN] == '\0'))) {
alanb@42307 329 const char* class_loader_name = SystemDictionary::loader_name(h_loader());
redestad@43466 330 size_t pkg_len = strlen(package_name);
redestad@43466 331 char* pkg_name = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, pkg_len);
redestad@43466 332 strncpy(pkg_name, package_name, pkg_len);
redestad@43466 333 StringUtils::replace_no_expand(pkg_name, "/", ".");
alanb@42307 334 const char* msg_text1 = "Class loader (instance of): ";
alanb@42307 335 const char* msg_text2 = " tried to define prohibited package name: ";
redestad@43466 336 size_t len = strlen(msg_text1) + strlen(class_loader_name) + strlen(msg_text2) + pkg_len + 1;
alanb@42307 337 char* message = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, len);
redestad@43466 338 jio_snprintf(message, len, "%s%s%s%s", msg_text1, class_loader_name, msg_text2, pkg_name);
alanb@42307 339 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), message);
alanb@42307 340 }
alanb@42307 341
alanb@36508 342 Symbol* pkg_symbol = SymbolTable::new_symbol(package_name, CHECK);
hseigel@46322 343 pkg_list->append(pkg_symbol);
alanb@36508 344 }
alanb@36508 345
alanb@36508 346 ModuleEntryTable* module_table = get_module_entry_table(h_loader, CHECK);
alanb@36508 347 assert(module_table != NULL, "module entry table shouldn't be null");
alanb@36508 348
alanb@36508 349 // Create symbol* entry for module name.
alanb@36508 350 TempNewSymbol module_symbol = SymbolTable::new_symbol(module_name, CHECK);
alanb@36508 351
alanb@36508 352 bool dupl_modules = false;
alanb@36508 353
alanb@36508 354 // Create symbol* entry for module version.
alanb@36508 355 TempNewSymbol version_symbol;
alanb@36508 356 if (module_version != NULL) {
alanb@36508 357 version_symbol = SymbolTable::new_symbol(module_version, CHECK);
alanb@36508 358 } else {
alanb@36508 359 version_symbol = NULL;
alanb@36508 360 }
alanb@36508 361
alanb@36508 362 // Create symbol* entry for module location.
alanb@36508 363 const char* module_location = NULL;
alanb@36508 364 TempNewSymbol location_symbol = NULL;
alanb@36508 365 if (location != NULL) {
alanb@36508 366 module_location =
alanb@36508 367 java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(location));
alanb@36508 368 if (module_location != NULL) {
alanb@36508 369 location_symbol = SymbolTable::new_symbol(module_location, CHECK);
alanb@36508 370 }
alanb@36508 371 }
alanb@36508 372
alanb@36508 373 ClassLoaderData* loader_data = ClassLoaderData::class_loader_data_or_null(h_loader());
alanb@36508 374 assert(loader_data != NULL, "class loader data shouldn't be null");
alanb@36508 375
alanb@36508 376 PackageEntryTable* package_table = NULL;
hseigel@43446 377 PackageEntry* existing_pkg = NULL;
alanb@36508 378 {
alanb@36508 379 MutexLocker ml(Module_lock, THREAD);
alanb@36508 380
alanb@36508 381 if (num_packages > 0) {
alanb@36508 382 package_table = get_package_entry_table(h_loader, CHECK);
alanb@36508 383 assert(package_table != NULL, "Missing package_table");
alanb@36508 384
alanb@36508 385 // Check that none of the packages exist in the class loader's package table.
alanb@36508 386 for (int x = 0; x < pkg_list->length(); x++) {
hseigel@43446 387 existing_pkg = package_table->lookup_only(pkg_list->at(x));
hseigel@43446 388 if (existing_pkg != NULL) {
alanb@36508 389 // This could be because the module was already defined. If so,
alanb@36508 390 // report that error instead of the package error.
alanb@36508 391 if (module_table->lookup_only(module_symbol) != NULL) {
alanb@36508 392 dupl_modules = true;
alanb@36508 393 }
alanb@36508 394 break;
alanb@36508 395 }
alanb@36508 396 }
alanb@36508 397 } // if (num_packages > 0)...
alanb@36508 398
alanb@36508 399 // Add the module and its packages.
hseigel@43446 400 if (!dupl_modules && existing_pkg == NULL) {
alanb@36508 401 // Create the entry for this module in the class loader's module entry table.
rprotacio@46404 402 ModuleEntry* module_entry = module_table->locked_create_entry_or_null(module_handle,
rprotacio@46404 403 (is_open == JNI_TRUE), module_symbol,
alanb@36508 404 version_symbol, location_symbol, loader_data);
alanb@36508 405
alanb@36508 406 if (module_entry == NULL) {
alanb@36508 407 dupl_modules = true;
alanb@36508 408 } else {
alanb@36508 409 // Add the packages.
alanb@36508 410 assert(pkg_list->length() == 0 || package_table != NULL, "Bad package table");
alanb@36508 411 PackageEntry* pkg;
alanb@36508 412 for (int y = 0; y < pkg_list->length(); y++) {
alanb@36508 413 pkg = package_table->locked_create_entry_or_null(pkg_list->at(y), module_entry);
alanb@36508 414 assert(pkg != NULL, "Unable to create a module's package entry");
alanb@36508 415
alanb@36508 416 // Unable to have a GrowableArray of TempNewSymbol. Must decrement the refcount of
alanb@36508 417 // the Symbol* that was created above for each package. The refcount was incremented
alanb@36508 418 // by SymbolTable::new_symbol and as well by the PackageEntry creation.
alanb@36508 419 pkg_list->at(y)->decrement_refcount();
alanb@36508 420 }
alanb@36508 421
alanb@44520 422 // Store pointer to ModuleEntry record in java.lang.Module object.
alanb@44520 423 java_lang_Module::set_module_entry(module_handle(), module_entry);
alanb@36508 424 }
alanb@36508 425 }
alanb@36508 426 } // Release the lock
alanb@36508 427
alanb@36508 428 // any errors ?
alanb@36508 429 if (dupl_modules) {
hseigel@43446 430 THROW_MSG(vmSymbols::java_lang_IllegalStateException(),
alanb@36508 431 err_msg("Module %s is already defined", module_name));
hseigel@43446 432 } else if (existing_pkg != NULL) {
hseigel@43446 433 throw_dup_pkg_exception(module_name, existing_pkg, CHECK);
alanb@36508 434 }
alanb@36508 435
alanb@44993 436 log_info(module, load)("%s location: %s", module_name,
alanb@44993 437 module_location != NULL ? module_location : "NULL");
alanb@44993 438 if (log_is_enabled(Debug, module)) {
alanb@44993 439 outputStream* logst = Log(module)::debug_stream();
alanb@36508 440 logst->print("define_module(): creation of module: %s, version: %s, location: %s, ",
alanb@36508 441 module_name, module_version != NULL ? module_version : "NULL",
alanb@36508 442 module_location != NULL ? module_location : "NULL");
alanb@36508 443 loader_data->print_value_on(logst);
alanb@36508 444 logst->print_cr(", package #: %d", pkg_list->length());
alanb@36508 445 for (int y = 0; y < pkg_list->length(); y++) {
alanb@44993 446 log_trace(module)("define_module(): creation of package %s for module %s",
alanb@44993 447 (pkg_list->at(y))->as_C_string(), module_name);
alanb@36508 448 }
alanb@36508 449 }
alanb@36508 450
alanb@37773 451 // If the module is defined to the boot loader and an exploded build is being
hseigel@46463 452 // used, prepend <java.home>/modules/modules_name to the system boot class path.
hseigel@46463 453 if (loader == NULL && !ClassLoader::has_jrt_entry()) {
lfoltan@40013 454 ClassLoader::add_to_exploded_build_list(module_symbol, CHECK);
alanb@36508 455 }
alanb@36508 456 }
alanb@36508 457
alanb@36508 458 void Modules::set_bootloader_unnamed_module(jobject module, TRAPS) {
alanb@36508 459 ResourceMark rm(THREAD);
alanb@36508 460
alanb@36508 461 if (module == NULL) {
alanb@36508 462 THROW_MSG(vmSymbols::java_lang_NullPointerException(), "Null module object");
alanb@36508 463 }
alanb@36508 464 Handle module_handle(THREAD, JNIHandles::resolve(module));
alanb@44520 465 if (!java_lang_Module::is_instance(module_handle())) {
alanb@36508 466 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
alanb@44520 467 "module is not an instance of type java.lang.Module");
alanb@36508 468 }
alanb@36508 469
alanb@36508 470 // Ensure that this is an unnamed module
alanb@44520 471 oop name = java_lang_Module::name(module_handle());
alanb@36508 472 if (name != NULL) {
alanb@36508 473 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
alanb@44520 474 "boot loader's unnamed module's java.lang.Module has a name");
alanb@36508 475 }
alanb@36508 476
alanb@36508 477 // Validate java_base's loader is the boot loader.
alanb@44520 478 oop loader = java_lang_Module::loader(module_handle());
alanb@36508 479 if (loader != NULL) {
alanb@36508 480 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
alanb@36508 481 "Class loader must be the boot class loader");
alanb@36508 482 }
coleenp@46271 483 Handle h_loader(THREAD, loader);
alanb@36508 484
alanb@44993 485 log_debug(module)("set_bootloader_unnamed_module(): recording unnamed module for boot loader");
alanb@36508 486
alanb@44520 487 // Set java.lang.Module for the boot loader's unnamed module
rprotacio@46387 488 ClassLoaderData* boot_loader_data = ClassLoaderData::the_null_class_loader_data();
rprotacio@46387 489 ModuleEntry* unnamed_module = boot_loader_data->unnamed_module();
alanb@36508 490 assert(unnamed_module != NULL, "boot loader's unnamed ModuleEntry not defined");
rprotacio@46387 491 unnamed_module->set_module(boot_loader_data->add_handle(module_handle));
alanb@44520 492 // Store pointer to the ModuleEntry in the unnamed module's java.lang.Module object.
alanb@44520 493 java_lang_Module::set_module_entry(module_handle(), unnamed_module);
alanb@36508 494 }
alanb@36508 495
redestad@43466 496 void Modules::add_module_exports(jobject from_module, const char* package_name, jobject to_module, TRAPS) {
redestad@43466 497 if (package_name == NULL) {
alanb@36508 498 THROW_MSG(vmSymbols::java_lang_NullPointerException(),
alanb@36508 499 "package is null");
alanb@36508 500 }
alanb@36508 501 if (from_module == NULL) {
alanb@36508 502 THROW_MSG(vmSymbols::java_lang_NullPointerException(),
alanb@36508 503 "from_module is null");
alanb@36508 504 }
alanb@36508 505 ModuleEntry* from_module_entry = get_module_entry(from_module, CHECK);
alanb@36508 506 if (from_module_entry == NULL) {
alanb@36508 507 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
alanb@36508 508 "from_module cannot be found");
alanb@36508 509 }
alanb@36508 510
rprotacio@46404 511 // All packages in unnamed and open modules are exported by default.
rprotacio@46404 512 if (!from_module_entry->is_named() || from_module_entry->is_open()) return;
alanb@36508 513
alanb@36508 514 ModuleEntry* to_module_entry;
alanb@36508 515 if (to_module == NULL) {
alanb@36508 516 to_module_entry = NULL; // It's an unqualified export.
alanb@36508 517 } else {
alanb@36508 518 to_module_entry = get_module_entry(to_module, CHECK);
alanb@36508 519 if (to_module_entry == NULL) {
alanb@36508 520 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
alanb@36508 521 "to_module is invalid");
alanb@36508 522 }
alanb@36508 523 }
alanb@36508 524
redestad@43466 525 PackageEntry *package_entry = get_package_entry(from_module_entry, package_name, CHECK);
alanb@36508 526 ResourceMark rm(THREAD);
alanb@36508 527 if (package_entry == NULL) {
alanb@36508 528 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
alanb@36508 529 err_msg("Package %s not found in from_module %s",
alanb@36508 530 package_name != NULL ? package_name : "",
alanb@36508 531 from_module_entry->name()->as_C_string()));
alanb@36508 532 }
alanb@36508 533 if (package_entry->module() != from_module_entry) {
alanb@36508 534 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
alanb@36508 535 err_msg("Package: %s found in module %s, not in from_module: %s",
alanb@36508 536 package_entry->name()->as_C_string(),
alanb@36508 537 package_entry->module()->name()->as_C_string(),
alanb@36508 538 from_module_entry->name()->as_C_string()));
alanb@36508 539 }
alanb@36508 540
alanb@44993 541 log_debug(module)("add_module_exports(): package %s in module %s is exported to module %s",
alanb@44993 542 package_entry->name()->as_C_string(),
alanb@44993 543 from_module_entry->name()->as_C_string(),
alanb@44993 544 to_module_entry == NULL ? "NULL" :
alanb@36508 545 to_module_entry->is_named() ?
alanb@36508 546 to_module_entry->name()->as_C_string() : UNNAMED_MODULE);
alanb@36508 547
lfoltan@39290 548 // Do nothing if modules are the same.
lfoltan@39290 549 if (from_module_entry != to_module_entry) {
alanb@36508 550 package_entry->set_exported(to_module_entry);
alanb@36508 551 }
alanb@36508 552 }
alanb@36508 553
alanb@36508 554
redestad@43466 555 void Modules::add_module_exports_qualified(jobject from_module, const char* package,
alanb@36508 556 jobject to_module, TRAPS) {
alanb@36508 557 if (to_module == NULL) {
alanb@36508 558 THROW_MSG(vmSymbols::java_lang_NullPointerException(),
alanb@36508 559 "to_module is null");
alanb@36508 560 }
alanb@36508 561 add_module_exports(from_module, package, to_module, CHECK);
alanb@36508 562 }
alanb@36508 563
alanb@36508 564 void Modules::add_reads_module(jobject from_module, jobject to_module, TRAPS) {
alanb@36508 565 if (from_module == NULL) {
alanb@36508 566 THROW_MSG(vmSymbols::java_lang_NullPointerException(),
alanb@36508 567 "from_module is null");
alanb@36508 568 }
alanb@36508 569
alanb@36508 570 ModuleEntry* from_module_entry = get_module_entry(from_module, CHECK);
alanb@36508 571 if (from_module_entry == NULL) {
alanb@36508 572 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
alanb@36508 573 "from_module is not valid");
alanb@36508 574 }
alanb@36508 575
alanb@36508 576 ModuleEntry* to_module_entry;
alanb@36508 577 if (to_module != NULL) {
alanb@36508 578 to_module_entry = get_module_entry(to_module, CHECK);
alanb@36508 579 if (to_module_entry == NULL) {
alanb@36508 580 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
alanb@36508 581 "to_module is invalid");
alanb@36508 582 }
alanb@36508 583 } else {
alanb@36508 584 to_module_entry = NULL;
alanb@36508 585 }
alanb@36508 586
alanb@36508 587 ResourceMark rm(THREAD);
alanb@44993 588 log_debug(module)("add_reads_module(): Adding read from module %s to module %s",
alanb@44993 589 from_module_entry->is_named() ?
alanb@44993 590 from_module_entry->name()->as_C_string() : UNNAMED_MODULE,
alanb@44993 591 to_module_entry == NULL ? "all unnamed" :
alanb@44993 592 (to_module_entry->is_named() ?
alanb@44993 593 to_module_entry->name()->as_C_string() : UNNAMED_MODULE));
alanb@36508 594
alanb@36508 595 // if modules are the same or if from_module is unnamed then no need to add the read.
alanb@36508 596 if (from_module_entry != to_module_entry && from_module_entry->is_named()) {
alanb@36508 597 from_module_entry->add_read(to_module_entry);
alanb@36508 598 }
alanb@36508 599 }
alanb@36508 600
alanb@36508 601 // This method is called by JFR and JNI.
alanb@36508 602 jobject Modules::get_module(jclass clazz, TRAPS) {
rprotacio@42636 603 assert(ModuleEntryTable::javabase_defined(),
rprotacio@42636 604 "Attempt to call get_module before " JAVA_BASE_NAME " is defined");
alanb@36508 605
alanb@36508 606 if (clazz == NULL) {
alanb@36508 607 THROW_MSG_(vmSymbols::java_lang_NullPointerException(),
alanb@36508 608 "class is null", JNI_FALSE);
alanb@36508 609 }
alanb@36508 610 oop mirror = JNIHandles::resolve_non_null(clazz);
alanb@36508 611 if (mirror == NULL) {
alanb@44993 612 log_debug(module)("get_module(): no mirror, returning NULL");
alanb@36508 613 return NULL;
alanb@36508 614 }
alanb@36508 615 if (!java_lang_Class::is_instance(mirror)) {
alanb@36508 616 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
alanb@36508 617 "Invalid class", JNI_FALSE);
alanb@36508 618 }
alanb@36508 619
alanb@36508 620 oop module = java_lang_Class::module(mirror);
alanb@36508 621
alanb@36508 622 assert(module != NULL, "java.lang.Class module field not set");
alanb@44520 623 assert(java_lang_Module::is_instance(module), "module is not an instance of type java.lang.Module");
alanb@36508 624
alanb@44993 625 if (log_is_enabled(Debug, module)) {
alanb@36508 626 ResourceMark rm(THREAD);
alanb@44993 627 outputStream* logst = Log(module)::debug_stream();
alanb@36508 628 Klass* klass = java_lang_Class::as_Klass(mirror);
alanb@44520 629 oop module_name = java_lang_Module::name(module);
alanb@36508 630 if (module_name != NULL) {
alanb@36508 631 logst->print("get_module(): module ");
alanb@36508 632 java_lang_String::print(module_name, tty);
alanb@36508 633 } else {
alanb@36508 634 logst->print("get_module(): Unamed Module");
alanb@36508 635 }
alanb@36508 636 if (klass != NULL) {
alanb@36508 637 logst->print_cr(" for class %s", klass->external_name());
alanb@36508 638 } else {
alanb@36508 639 logst->print_cr(" for primitive class");
alanb@36508 640 }
alanb@36508 641 }
alanb@36508 642
alanb@36508 643 return JNIHandles::make_local(THREAD, module);
alanb@36508 644 }
alanb@36508 645
redestad@43466 646 jobject Modules::get_named_module(Handle h_loader, const char* package_name, TRAPS) {
sspitsyn@39706 647 assert(ModuleEntryTable::javabase_defined(),
rprotacio@42636 648 "Attempt to call get_named_module before " JAVA_BASE_NAME " is defined");
sspitsyn@39706 649 assert(h_loader.is_null() || java_lang_ClassLoader::is_subclass(h_loader->klass()),
sspitsyn@39706 650 "Class loader is not a subclass of java.lang.ClassLoader");
redestad@43466 651 assert(package_name != NULL, "the package_name should not be NULL");
sspitsyn@39706 652
redestad@43466 653 if (strlen(package_name) == 0) {
sspitsyn@39706 654 return NULL;
sspitsyn@39706 655 }
redestad@43466 656 TempNewSymbol package_sym = SymbolTable::new_symbol(package_name, CHECK_NULL);
sspitsyn@39706 657 const PackageEntry* const pkg_entry =
sspitsyn@39706 658 get_package_entry_by_name(package_sym, h_loader, THREAD);
sspitsyn@39706 659 const ModuleEntry* const module_entry = (pkg_entry != NULL ? pkg_entry->module() : NULL);
sspitsyn@39706 660
sspitsyn@39706 661 if (module_entry != NULL && module_entry->module() != NULL && module_entry->is_named()) {
sspitsyn@39706 662 return JNIHandles::make_local(THREAD, JNIHandles::resolve(module_entry->module()));
sspitsyn@39706 663 }
sspitsyn@39706 664 return NULL;
sspitsyn@39706 665 }
sspitsyn@39706 666
sspitsyn@39706 667
alanb@36508 668 // This method is called by JFR and by the above method.
alanb@36508 669 jobject Modules::get_module(Symbol* package_name, Handle h_loader, TRAPS) {
alanb@36508 670 const PackageEntry* const pkg_entry =
alanb@36508 671 get_package_entry_by_name(package_name, h_loader, THREAD);
alanb@36508 672 const ModuleEntry* const module_entry = (pkg_entry != NULL ? pkg_entry->module() : NULL);
alanb@36508 673
alanb@36508 674 if (module_entry != NULL &&
alanb@36508 675 module_entry->module() != NULL) {
alanb@36508 676 return JNIHandles::make_local(THREAD, JNIHandles::resolve(module_entry->module()));
alanb@36508 677 }
alanb@36508 678
alanb@36508 679 return NULL;
alanb@36508 680 }
alanb@36508 681
redestad@43466 682 void Modules::add_module_package(jobject module, const char* package_name, TRAPS) {
alanb@36508 683 ResourceMark rm(THREAD);
alanb@36508 684
alanb@36508 685 if (module == NULL) {
alanb@36508 686 THROW_MSG(vmSymbols::java_lang_NullPointerException(),
alanb@36508 687 "module is null");
alanb@36508 688 }
redestad@43466 689 if (package_name == NULL) {
alanb@36508 690 THROW_MSG(vmSymbols::java_lang_NullPointerException(),
alanb@36508 691 "package is null");
alanb@36508 692 }
alanb@36508 693 ModuleEntry* module_entry = get_module_entry(module, CHECK);
alanb@36508 694 if (module_entry == NULL) {
alanb@36508 695 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
alanb@36508 696 "module is invalid");
alanb@36508 697 }
alanb@36508 698 if (!module_entry->is_named()) {
alanb@36508 699 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
alanb@36508 700 "module cannot be an unnamed module");
alanb@36508 701 }
alanb@36508 702 if (!verify_package_name(package_name)) {
alanb@36508 703 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
alanb@36508 704 err_msg("Invalid package name: %s", package_name));
alanb@36508 705 }
alanb@36508 706
alanb@42307 707 ClassLoaderData *loader_data = module_entry->loader_data();
alanb@42307 708
alanb@42307 709 // Only modules defined to either the boot or platform class loader, can define a "java/" package.
alanb@42307 710 if (!loader_data->is_the_null_class_loader_data() &&
alanb@42307 711 !loader_data->is_platform_class_loader_data() &&
alanb@44326 712 (strncmp(package_name, JAVAPKG, JAVAPKG_LEN) == 0 &&
alanb@44326 713 (package_name[JAVAPKG_LEN] == '/' || package_name[JAVAPKG_LEN] == '\0'))) {
alanb@42307 714 const char* class_loader_name = SystemDictionary::loader_name(loader_data);
redestad@43466 715 size_t pkg_len = strlen(package_name);
redestad@43466 716 char* pkg_name = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, pkg_len);
redestad@43466 717 strncpy(pkg_name, package_name, pkg_len);
redestad@43466 718 StringUtils::replace_no_expand(pkg_name, "/", ".");
alanb@42307 719 const char* msg_text1 = "Class loader (instance of): ";
alanb@42307 720 const char* msg_text2 = " tried to define prohibited package name: ";
redestad@43466 721 size_t len = strlen(msg_text1) + strlen(class_loader_name) + strlen(msg_text2) + pkg_len + 1;
alanb@42307 722 char* message = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, len);
redestad@43466 723 jio_snprintf(message, len, "%s%s%s%s", msg_text1, class_loader_name, msg_text2, pkg_name);
alanb@42307 724 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), message);
alanb@42307 725 }
alanb@42307 726
alanb@44993 727 log_debug(module)("add_module_package(): Adding package %s to module %s",
alanb@44993 728 package_name, module_entry->name()->as_C_string());
alanb@36508 729
alanb@36508 730 TempNewSymbol pkg_symbol = SymbolTable::new_symbol(package_name, CHECK);
alanb@42307 731 PackageEntryTable* package_table = loader_data->packages();
alanb@36508 732 assert(package_table != NULL, "Missing package_table");
alanb@36508 733
hseigel@43446 734 PackageEntry* existing_pkg = NULL;
alanb@36508 735 {
alanb@36508 736 MutexLocker ml(Module_lock, THREAD);
alanb@36508 737
alanb@36508 738 // Check that the package does not exist in the class loader's package table.
hseigel@43446 739 existing_pkg = package_table->lookup_only(pkg_symbol);
hseigel@43446 740 if (existing_pkg == NULL) {
alanb@36508 741 PackageEntry* pkg = package_table->locked_create_entry_or_null(pkg_symbol, module_entry);
alanb@36508 742 assert(pkg != NULL, "Unable to create a module's package entry");
alanb@36508 743 }
alanb@36508 744 }
hseigel@43446 745 if (existing_pkg != NULL) {
hseigel@43446 746 throw_dup_pkg_exception(module_entry->name()->as_C_string(), existing_pkg, CHECK);
alanb@36508 747 }
alanb@36508 748 }
alanb@36508 749
alanb@36508 750 // Export package in module to all unnamed modules.
redestad@43466 751 void Modules::add_module_exports_to_all_unnamed(jobject module, const char* package_name, TRAPS) {
alanb@36508 752 if (module == NULL) {
alanb@36508 753 THROW_MSG(vmSymbols::java_lang_NullPointerException(),
alanb@36508 754 "module is null");
alanb@36508 755 }
redestad@43466 756 if (package_name == NULL) {
alanb@36508 757 THROW_MSG(vmSymbols::java_lang_NullPointerException(),
alanb@36508 758 "package is null");
alanb@36508 759 }
alanb@36508 760 ModuleEntry* module_entry = get_module_entry(module, CHECK);
alanb@36508 761 if (module_entry == NULL) {
alanb@36508 762 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
alanb@36508 763 "module is invalid");
alanb@36508 764 }
alanb@36508 765
alanb@36508 766 if (module_entry->is_named()) { // No-op for unnamed module.
redestad@43466 767 PackageEntry *package_entry = get_package_entry(module_entry, package_name, CHECK);
alanb@36508 768 ResourceMark rm(THREAD);
alanb@36508 769 if (package_entry == NULL) {
alanb@36508 770 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
alanb@36508 771 err_msg("Package %s not found in module %s",
alanb@36508 772 package_name != NULL ? package_name : "",
alanb@36508 773 module_entry->name()->as_C_string()));
alanb@36508 774 }
alanb@36508 775 if (package_entry->module() != module_entry) {
alanb@36508 776 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
alanb@36508 777 err_msg("Package: %s found in module %s, not in module: %s",
alanb@36508 778 package_entry->name()->as_C_string(),
alanb@36508 779 package_entry->module()->name()->as_C_string(),
alanb@36508 780 module_entry->name()->as_C_string()));
alanb@36508 781 }
alanb@36508 782
alanb@44993 783 log_debug(module)("add_module_exports_to_all_unnamed(): package %s in module"
alanb@44993 784 " %s is exported to all unnamed modules",
alanb@36508 785 package_entry->name()->as_C_string(),
alanb@36508 786 module_entry->name()->as_C_string());
alanb@36508 787
hseigel@43471 788 // Mark package as exported to all unnamed modules.
hseigel@43471 789 package_entry->set_is_exported_allUnnamed();
alanb@36508 790 }
alanb@36508 791 }