8169559: Add class loader names to relevant VM messages
Added new method class_in_module_of_loader to provide a standard format for class information within error messages. Reviewed-by: goetz, hseigel, mchung
This commit is contained in:
parent
fc73803071
commit
7ca4027957
src/hotspot/share
classfile
interpreter
oops
runtime
test/hotspot/jtreg
runtime
exceptionMsgs/IncompatibleClassChangeError
modules
vmTestbase/jit/t/t113
@ -955,9 +955,10 @@ void ClassFileParser::parse_interfaces(const ClassFileStream* const stream,
|
||||
|
||||
if (!interf->is_interface()) {
|
||||
THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(),
|
||||
err_msg("Class %s can not implement %s, because it is not an interface",
|
||||
err_msg("class %s can not implement %s, because it is not an interface (%s)",
|
||||
_class_name->as_klass_external_name(),
|
||||
interf->class_loader_and_module_name()));
|
||||
interf->external_name(),
|
||||
interf->class_in_module_of_loader()));
|
||||
}
|
||||
|
||||
if (InstanceKlass::cast(interf)->has_nonstatic_concrete_methods()) {
|
||||
|
@ -40,10 +40,12 @@
|
||||
#include "jfr/support/jfrTraceIdExtension.hpp"
|
||||
#endif
|
||||
|
||||
#define UNNAMED_MODULE "Unnamed Module"
|
||||
#define UNNAMED_MODULE "unnamed module"
|
||||
#define UNNAMED_MODULE_LEN 14
|
||||
#define JAVAPKG "java"
|
||||
#define JAVAPKG_LEN 4
|
||||
#define JAVA_BASE_NAME "java.base"
|
||||
#define JAVA_BASE_NAME_LEN 9
|
||||
|
||||
class ModuleClosure;
|
||||
|
||||
|
@ -592,14 +592,18 @@ void LinkResolver::check_method_accessability(Klass* ref_klass,
|
||||
// from nest-host resolution, have been allowed to propagate.
|
||||
if (!can_access) {
|
||||
ResourceMark rm(THREAD);
|
||||
bool same_module = (sel_klass->module() == ref_klass->module());
|
||||
Exceptions::fthrow(
|
||||
THREAD_AND_LOCATION,
|
||||
vmSymbols::java_lang_IllegalAccessError(),
|
||||
"tried to access method %s.%s%s from class %s",
|
||||
"class %s tried to access method %s.%s%s (%s%s%s)",
|
||||
ref_klass->external_name(),
|
||||
sel_klass->external_name(),
|
||||
sel_method->name()->as_C_string(),
|
||||
sel_method->signature()->as_C_string(),
|
||||
ref_klass->external_name()
|
||||
(same_module) ? ref_klass->joint_in_module_of_loader(sel_klass) : ref_klass->class_in_module_of_loader(),
|
||||
(same_module) ? "" : "; ",
|
||||
(same_module) ? "" : sel_klass->class_in_module_of_loader()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
@ -2850,9 +2850,14 @@ Method* InstanceKlass::method_at_itable(Klass* holder, int index, TRAPS) {
|
||||
if (cnt >= nof_interfaces) {
|
||||
ResourceMark rm(THREAD);
|
||||
stringStream ss;
|
||||
bool same_module = (module() == holder->module());
|
||||
ss.print("Receiver class %s does not implement "
|
||||
"the interface %s defining the method to be called",
|
||||
class_loader_and_module_name(), holder->class_loader_and_module_name());
|
||||
"the interface %s defining the method to be called "
|
||||
"(%s%s%s)",
|
||||
external_name(), holder->external_name(),
|
||||
(same_module) ? joint_in_module_of_loader(holder) : class_in_module_of_loader(),
|
||||
(same_module) ? "" : "; ",
|
||||
(same_module) ? "" : holder->class_in_module_of_loader());
|
||||
THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string());
|
||||
}
|
||||
|
||||
|
@ -774,80 +774,124 @@ bool Klass::verify_itable_index(int i) {
|
||||
|
||||
#endif // PRODUCT
|
||||
|
||||
// The caller of class_loader_and_module_name() (or one of its callers)
|
||||
// must use a ResourceMark in order to correctly free the result.
|
||||
const char* Klass::class_loader_and_module_name() const {
|
||||
const char* delim = "/";
|
||||
size_t delim_len = strlen(delim);
|
||||
// Caller needs ResourceMark
|
||||
// joint_in_module_of_loader provides an optimization if 2 classes are in
|
||||
// the same module to succinctly print out relevant information about their
|
||||
// module name and class loader's name_and_id for error messages.
|
||||
// Format:
|
||||
// <fully-qualified-external-class-name1> and <fully-qualified-external-class-name2>
|
||||
// are in module <module-name>[@<version>]
|
||||
// of loader <loader-name_and_id>[, parent loader <parent-loader-name_and_id>]
|
||||
const char* Klass::joint_in_module_of_loader(const Klass* class2, bool include_parent_loader) const {
|
||||
assert(module() == class2->module(), "classes do not have the same module");
|
||||
const char* class1_name = external_name();
|
||||
size_t len = strlen(class1_name) + 1;
|
||||
|
||||
const char* fqn = external_name();
|
||||
// Length of message to return; always include FQN
|
||||
size_t msglen = strlen(fqn) + 1;
|
||||
const char* class2_description = class2->class_in_module_of_loader(true, include_parent_loader);
|
||||
len += strlen(class2_description);
|
||||
|
||||
bool has_cl_name = false;
|
||||
bool has_mod_name = false;
|
||||
bool has_version = false;
|
||||
len += strlen(" and ");
|
||||
|
||||
// Use class loader name, if exists and not builtin
|
||||
const char* class_loader_name = "";
|
||||
ClassLoaderData* cld = class_loader_data();
|
||||
assert(cld != NULL, "class_loader_data should not be NULL");
|
||||
if (!cld->is_builtin_class_loader_data()) {
|
||||
// If not builtin, look for name
|
||||
oop loader = class_loader();
|
||||
if (loader != NULL) {
|
||||
oop class_loader_name_oop = java_lang_ClassLoader::name(loader);
|
||||
if (class_loader_name_oop != NULL) {
|
||||
class_loader_name = java_lang_String::as_utf8_string(class_loader_name_oop);
|
||||
if (class_loader_name != NULL && class_loader_name[0] != '\0') {
|
||||
has_cl_name = true;
|
||||
msglen += strlen(class_loader_name) + delim_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
char* joint_description = NEW_RESOURCE_ARRAY_RETURN_NULL(char, len);
|
||||
|
||||
// Just return the FQN if error when allocating string
|
||||
if (joint_description == NULL) {
|
||||
return class1_name;
|
||||
}
|
||||
|
||||
jio_snprintf(joint_description, len, "%s and %s",
|
||||
class1_name,
|
||||
class2_description);
|
||||
|
||||
return joint_description;
|
||||
}
|
||||
|
||||
// Caller needs ResourceMark
|
||||
// class_in_module_of_loader provides a standard way to include
|
||||
// relevant information about a class, such as its module name as
|
||||
// well as its class loader's name_and_id, in error messages and logging.
|
||||
// Format:
|
||||
// <fully-qualified-external-class-name> is in module <module-name>[@<version>]
|
||||
// of loader <loader-name_and_id>[, parent loader <parent-loader-name_and_id>]
|
||||
const char* Klass::class_in_module_of_loader(bool use_are, bool include_parent_loader) const {
|
||||
// 1. fully qualified external name of class
|
||||
const char* klass_name = external_name();
|
||||
size_t len = strlen(klass_name) + 1;
|
||||
|
||||
// 2. module name + @version
|
||||
const char* module_name = "";
|
||||
const char* version = "";
|
||||
bool has_version = false;
|
||||
bool module_is_named = false;
|
||||
const char* module_name_phrase = "";
|
||||
const Klass* bottom_klass = is_objArray_klass() ?
|
||||
ObjArrayKlass::cast(this)->bottom_klass() : this;
|
||||
ObjArrayKlass::cast(this)->bottom_klass() : this;
|
||||
if (bottom_klass->is_instance_klass()) {
|
||||
ModuleEntry* module = InstanceKlass::cast(bottom_klass)->module();
|
||||
// Use module name, if exists
|
||||
if (module->is_named()) {
|
||||
has_mod_name = true;
|
||||
module_is_named = true;
|
||||
module_name_phrase = "module ";
|
||||
module_name = module->name()->as_C_string();
|
||||
msglen += strlen(module_name);
|
||||
len += strlen(module_name);
|
||||
// Use version if exists and is not a jdk module
|
||||
if (module->should_show_version()) {
|
||||
has_version = true;
|
||||
version = module->version()->as_C_string();
|
||||
msglen += strlen(version) + 1; // +1 for "@"
|
||||
// Include stlen(version) + 1 for the "@"
|
||||
len += strlen(version) + 1;
|
||||
}
|
||||
} else {
|
||||
module_name = UNNAMED_MODULE;
|
||||
len += UNNAMED_MODULE_LEN;
|
||||
}
|
||||
} else {
|
||||
// klass is an array of primitives, so its module is java.base
|
||||
// klass is an array of primitives, module is java.base
|
||||
module_is_named = true;
|
||||
module_name_phrase = "module ";
|
||||
module_name = JAVA_BASE_NAME;
|
||||
len += JAVA_BASE_NAME_LEN;
|
||||
}
|
||||
|
||||
if (has_cl_name || has_mod_name) {
|
||||
msglen += delim_len;
|
||||
// 3. class loader's name_and_id
|
||||
ClassLoaderData* cld = class_loader_data();
|
||||
assert(cld != NULL, "class_loader_data should not be null");
|
||||
const char* loader_name_and_id = cld->loader_name_and_id();
|
||||
len += strlen(loader_name_and_id);
|
||||
|
||||
// 4. include parent loader information
|
||||
const char* parent_loader_phrase = "";
|
||||
const char* parent_loader_name_and_id = "";
|
||||
if (include_parent_loader &&
|
||||
!cld->is_builtin_class_loader_data()) {
|
||||
oop parent_loader = java_lang_ClassLoader::parent(class_loader());
|
||||
ClassLoaderData *parent_cld = ClassLoaderData::class_loader_data(parent_loader);
|
||||
assert(parent_cld != NULL, "parent's class loader data should not be null");
|
||||
parent_loader_name_and_id = parent_cld->loader_name_and_id();
|
||||
parent_loader_phrase = ", parent loader ";
|
||||
len += strlen(parent_loader_phrase) + strlen(parent_loader_name_and_id);
|
||||
}
|
||||
|
||||
char* message = NEW_RESOURCE_ARRAY_RETURN_NULL(char, msglen);
|
||||
// Start to construct final full class description string
|
||||
len += ((use_are) ? strlen(" are in ") : strlen(" is in "));
|
||||
len += strlen(module_name_phrase) + strlen(" of loader ");
|
||||
|
||||
// Just return the FQN if error in allocating string
|
||||
if (message == NULL) {
|
||||
return fqn;
|
||||
char* class_description = NEW_RESOURCE_ARRAY_RETURN_NULL(char, len);
|
||||
|
||||
// Just return the FQN if error when allocating string
|
||||
if (class_description == NULL) {
|
||||
return klass_name;
|
||||
}
|
||||
|
||||
jio_snprintf(message, msglen, "%s%s%s%s%s%s%s",
|
||||
class_loader_name,
|
||||
(has_cl_name) ? delim : "",
|
||||
(has_mod_name) ? module_name : "",
|
||||
jio_snprintf(class_description, len, "%s %s in %s%s%s%s of loader %s%s%s",
|
||||
klass_name,
|
||||
(use_are) ? "are" : "is",
|
||||
module_name_phrase,
|
||||
module_name,
|
||||
(has_version) ? "@" : "",
|
||||
(has_version) ? version : "",
|
||||
(has_cl_name || has_mod_name) ? delim : "",
|
||||
fqn);
|
||||
return message;
|
||||
loader_name_and_id,
|
||||
parent_loader_phrase,
|
||||
parent_loader_name_and_id);
|
||||
|
||||
return class_description;
|
||||
}
|
||||
|
@ -560,7 +560,8 @@ protected:
|
||||
// and the package separators as '/'.
|
||||
virtual const char* signature_name() const;
|
||||
|
||||
const char* class_loader_and_module_name() const;
|
||||
const char* joint_in_module_of_loader(const Klass* class2, bool include_parent_loader = false) const;
|
||||
const char* class_in_module_of_loader(bool use_are = false, bool include_parent_loader = false) const;
|
||||
|
||||
// Returns "interface", "abstract class" or "class".
|
||||
const char* external_kind() const;
|
||||
|
@ -1959,14 +1959,27 @@ char* SharedRuntime::generate_class_cast_message(
|
||||
// must use a ResourceMark in order to correctly free the result.
|
||||
char* SharedRuntime::generate_class_cast_message(
|
||||
Klass* caster_klass, Klass* target_klass, Symbol* target_klass_name) {
|
||||
|
||||
const char* caster_name = caster_klass->class_loader_and_module_name();
|
||||
const char* caster_name = caster_klass->external_name();
|
||||
|
||||
assert(target_klass != NULL || target_klass_name != NULL, "one must be provided");
|
||||
const char* target_name = target_klass == NULL ? target_klass_name->as_C_string() :
|
||||
target_klass->class_loader_and_module_name();
|
||||
target_klass->external_name();
|
||||
|
||||
size_t msglen = strlen(caster_name) + strlen(" cannot be cast to ") + strlen(target_name) + 1;
|
||||
size_t msglen = strlen(caster_name) + strlen("class ") + strlen(" cannot be cast to class ") + strlen(target_name) + 1;
|
||||
|
||||
const char* caster_klass_description = "";
|
||||
const char* target_klass_description = "";
|
||||
const char* klass_separator = "";
|
||||
if (target_klass != NULL && caster_klass->module() == target_klass->module()) {
|
||||
caster_klass_description = caster_klass->joint_in_module_of_loader(target_klass);
|
||||
} else {
|
||||
caster_klass_description = caster_klass->class_in_module_of_loader();
|
||||
target_klass_description = (target_klass != NULL) ? target_klass->class_in_module_of_loader() : "";
|
||||
klass_separator = (target_klass != NULL) ? "; " : "";
|
||||
}
|
||||
|
||||
// add 3 for parenthesis and preceeding space
|
||||
msglen += strlen(caster_klass_description) + strlen(target_klass_description) + strlen(klass_separator) + 3;
|
||||
|
||||
char* message = NEW_RESOURCE_ARRAY_RETURN_NULL(char, msglen);
|
||||
if (message == NULL) {
|
||||
@ -1975,9 +1988,13 @@ char* SharedRuntime::generate_class_cast_message(
|
||||
} else {
|
||||
jio_snprintf(message,
|
||||
msglen,
|
||||
"%s cannot be cast to %s",
|
||||
"class %s cannot be cast to class %s (%s%s%s)",
|
||||
caster_name,
|
||||
target_name);
|
||||
target_name,
|
||||
caster_klass_description,
|
||||
klass_separator,
|
||||
target_klass_description
|
||||
);
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
@ -212,7 +212,7 @@ public class IncompatibleClassChangeErrorTest {
|
||||
}
|
||||
|
||||
private static String expectedErrorMessage3 =
|
||||
"Class test.ICC3_B can not implement test.ICC3_A, because it is not an interface";
|
||||
"class test.ICC3_B can not implement test.ICC3_A, because it is not an interface (test.ICC3_A is in unnamed module of loader 'app')";
|
||||
|
||||
public static void test3_implementsClass() throws Exception {
|
||||
try {
|
||||
|
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Test that if module m1x can read module m2x, AND package p2 in m2x is
|
||||
* exported qualifiedly to m1x, then class p1.c1 in m1x can read p2.c2 in m2x.
|
||||
* However, p1.c1 tries to access a private method within p2.c2, verify
|
||||
* that the IAE message contains the correct loader and module names.
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* @library /test/lib
|
||||
* @compile p1/c1.jasm
|
||||
* @compile p2/c2.jasm
|
||||
* @compile myloaders/MySameClassLoader.java
|
||||
* @run main/othervm -Xbootclasspath/a:. ExpQualToM1PrivateMethodIAE
|
||||
*/
|
||||
|
||||
import static jdk.test.lib.Asserts.*;
|
||||
|
||||
import java.lang.module.Configuration;
|
||||
import java.lang.module.ModuleDescriptor;
|
||||
import java.lang.module.ModuleFinder;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import myloaders.MySameClassLoader;
|
||||
|
||||
public class ExpQualToM1PrivateMethodIAE {
|
||||
|
||||
// Create a layer over the boot layer.
|
||||
// Define modules within this layer to test access between
|
||||
// publically defined classes within packages of those modules.
|
||||
public void createLayerOnBoot() throws Throwable {
|
||||
|
||||
// Define module: m1x
|
||||
// Can read: java.base, m2x
|
||||
// Packages: p1
|
||||
// Packages exported: p1 is exported unqualifiedly
|
||||
ModuleDescriptor descriptor_m1x =
|
||||
ModuleDescriptor.newModule("m1x")
|
||||
.requires("java.base")
|
||||
.requires("m2x")
|
||||
.exports("p1")
|
||||
.build();
|
||||
|
||||
// Define module: m2x
|
||||
// Can read: java.base
|
||||
// Packages: p2
|
||||
// Packages exported: p2 is exported qualifiedly to m1x
|
||||
ModuleDescriptor descriptor_m2x =
|
||||
ModuleDescriptor.newModule("m2x")
|
||||
.requires("java.base")
|
||||
.exports("p2", Set.of("m1x"))
|
||||
.build();
|
||||
|
||||
// Set up a ModuleFinder containing all modules for this layer.
|
||||
ModuleFinder finder = ModuleLibrary.of(descriptor_m1x, descriptor_m2x);
|
||||
|
||||
// Resolves "m1x"
|
||||
Configuration cf = ModuleLayer.boot()
|
||||
.configuration()
|
||||
.resolve(finder, ModuleFinder.of(), Set.of("m1x"));
|
||||
|
||||
// map each module to the same class loader for this test
|
||||
Map<String, ClassLoader> map = new HashMap<>();
|
||||
map.put("m1x", MySameClassLoader.loader1);
|
||||
map.put("m2x", MySameClassLoader.loader1);
|
||||
|
||||
// Create layer that contains m1x & m2x
|
||||
ModuleLayer layer = ModuleLayer.boot().defineModules(cf, map::get);
|
||||
|
||||
assertTrue(layer.findLoader("m1x") == MySameClassLoader.loader1);
|
||||
assertTrue(layer.findLoader("m2x") == MySameClassLoader.loader1);
|
||||
|
||||
// now use the same loader to load class p1.c1
|
||||
Class p1_c1_class = MySameClassLoader.loader1.loadClass("p1.c1");
|
||||
try {
|
||||
p1_c1_class.newInstance();
|
||||
throw new RuntimeException("Test Failed, an IAE should be thrown since p2/c2's method2 is private");
|
||||
} catch (IllegalAccessError e) {
|
||||
String message = e.getMessage();
|
||||
System.out.println(e.toString());
|
||||
// java.lang.IllegalAccessError:
|
||||
// tried to access method p2.c2.method2()V from class p1.c1 (p2.c2 is in module m2x of loader
|
||||
// myloaders.MySameClassLoader @<id>; p1.c1 is in module m1x of loader myloaders.MySameClassLoader @<id>)
|
||||
if (!message.contains("class p1.c1 tried to access method p2.c2.method2()V (p1.c1 is in module m1x of loader myloaders.MySameClassLoader @") ||
|
||||
!message.contains("; p2.c2 is in module m2x of loader myloaders.MySameClassLoader @")) {
|
||||
throw new RuntimeException("Test Failed, an IAE was thrown with the wrong message: " + e.toString());
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException("Test Failed, an IAE should be thrown since p2/c2's method2 is private");
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String args[]) throws Throwable {
|
||||
ExpQualToM1PrivateMethodIAE test = new ExpQualToM1PrivateMethodIAE();
|
||||
test.createLayerOnBoot();
|
||||
}
|
||||
}
|
43
test/hotspot/jtreg/runtime/modules/AccessCheck/p1/c1.jasm
Normal file
43
test/hotspot/jtreg/runtime/modules/AccessCheck/p1/c1.jasm
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package p1;
|
||||
|
||||
super public class c1 version 55:0 {
|
||||
|
||||
public Method "<init>":"()V"
|
||||
stack 2 locals 2
|
||||
{
|
||||
aload_0;
|
||||
invokespecial Method java/lang/Object."<init>":"()V";
|
||||
new class p2/c2;
|
||||
dup;
|
||||
invokespecial Method p2/c2."<init>":"()V";
|
||||
astore_1;
|
||||
aload_1;
|
||||
invokevirtual Method p2/c2.method2:"()V";
|
||||
return;
|
||||
}
|
||||
} // end Class c1
|
42
test/hotspot/jtreg/runtime/modules/AccessCheck/p2/c2.jasm
Normal file
42
test/hotspot/jtreg/runtime/modules/AccessCheck/p2/c2.jasm
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package p2;
|
||||
|
||||
super public class c2 version 55:0 {
|
||||
public Method "<init>":"()V"
|
||||
stack 1 locals 1
|
||||
{
|
||||
aload_0;
|
||||
invokespecial Method java/lang/Object."<init>":"()V";
|
||||
return;
|
||||
}
|
||||
|
||||
private Method method2:"()V"
|
||||
stack 0 locals 1
|
||||
{
|
||||
return;
|
||||
}
|
||||
} // end Class c2
|
@ -48,6 +48,7 @@ public class CCE_module_msg {
|
||||
public static void main(String[] args) throws Throwable {
|
||||
// Should not display version
|
||||
invalidObjectToDerived();
|
||||
invalidOriginalInnerToDerived();
|
||||
invalidTimeToDerived();
|
||||
invalidHeadersToDerived();
|
||||
// Should display version
|
||||
@ -66,8 +67,25 @@ public class CCE_module_msg {
|
||||
}
|
||||
throw new RuntimeException("ClassCastException wasn't thrown, test failed.");
|
||||
} catch (ClassCastException cce) {
|
||||
System.out.println(cce.getMessage());
|
||||
if (!cce.getMessage().contains("java.base/java.lang.Object cannot be cast to Derived")) {
|
||||
System.out.println(cce.toString());
|
||||
if (!cce.getMessage().contains("class java.lang.Object cannot be cast to class Derived (java.lang.Object is in module java.base of loader 'bootstrap'; Derived is in unnamed module of loader 'app')")) {
|
||||
throw new RuntimeException("Wrong message: " + cce.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void invalidOriginalInnerToDerived() {
|
||||
OriginalInner instance = new OriginalInner();
|
||||
int left = 23;
|
||||
int right = 42;
|
||||
try {
|
||||
for (int i = 0; i < 1; i += 1) {
|
||||
left = ((Derived) (java.lang.Object)instance).method(left, right);
|
||||
}
|
||||
throw new RuntimeException("ClassCastException wasn't thrown, test failed.");
|
||||
} catch (ClassCastException cce) {
|
||||
System.out.println(cce.toString());
|
||||
if (!cce.getMessage().contains("class OriginalInner cannot be cast to class Derived (OriginalInner and Derived are in unnamed module of loader 'app')")) {
|
||||
throw new RuntimeException("Wrong message: " + cce.getMessage());
|
||||
}
|
||||
}
|
||||
@ -84,8 +102,8 @@ public class CCE_module_msg {
|
||||
}
|
||||
throw new RuntimeException("ClassCastException wasn't thrown, test failed.");
|
||||
} catch (ClassCastException cce) {
|
||||
System.out.println(cce.getMessage());
|
||||
if (!cce.getMessage().contains("java.sql/java.sql.Time cannot be cast to Derived")) {
|
||||
System.out.println(cce.toString());
|
||||
if (!cce.getMessage().contains("class java.sql.Time cannot be cast to class Derived (java.sql.Time is in module java.sql of loader 'platform'; Derived is in unnamed module of loader 'app')")) {
|
||||
throw new RuntimeException("Wrong message: " + cce.getMessage());
|
||||
}
|
||||
}
|
||||
@ -102,8 +120,8 @@ public class CCE_module_msg {
|
||||
}
|
||||
throw new RuntimeException("ClassCastException wasn't thrown, test failed.");
|
||||
} catch (ClassCastException cce) {
|
||||
System.out.println(cce.getMessage());
|
||||
if (!cce.getMessage().contains("jdk.httpserver/com.sun.net.httpserver.Headers cannot be cast to Derived")) {
|
||||
System.out.println(cce.toString());
|
||||
if (!cce.getMessage().contains("class com.sun.net.httpserver.Headers cannot be cast to class Derived (com.sun.net.httpserver.Headers is in module jdk.httpserver of loader 'platform'; Derived is in unnamed module of loader 'app')")) {
|
||||
throw new RuntimeException("Wrong message: " + cce.getMessage());
|
||||
}
|
||||
}
|
||||
@ -132,10 +150,9 @@ public class CCE_module_msg {
|
||||
throw new RuntimeException("ClassCastException wasn't thrown, test failed.");
|
||||
} catch (ClassCastException cce) {
|
||||
String exception = cce.getMessage();
|
||||
System.out.println(exception);
|
||||
if (exception.contains("module_two/p2.c2") ||
|
||||
!(exception.contains("module_two@") &&
|
||||
exception.contains("/p2.c2 cannot be cast to java.base/java.lang.String"))) {
|
||||
System.out.println(cce.toString());
|
||||
if (!exception.contains("class p2.c2 cannot be cast to class java.lang.String (p2.c2 is in module module_two@") ||
|
||||
!exception.contains(" of loader 'app'; java.lang.String is in module java.base of loader 'bootstrap')")) {
|
||||
throw new RuntimeException("Wrong message: " + exception);
|
||||
}
|
||||
}
|
||||
@ -160,14 +177,21 @@ public class CCE_module_msg {
|
||||
throw new RuntimeException("ClassCastException wasn't thrown, test failed.");
|
||||
} catch (ClassCastException cce) {
|
||||
String exception = cce.getMessage();
|
||||
System.out.println(exception);
|
||||
if (!exception.contains("MyClassLoader//p4.c4 cannot be cast to java.base/java.lang.String")) {
|
||||
System.out.println(cce.toString());
|
||||
if (!exception.contains("class p4.c4 cannot be cast to class java.lang.String (p4.c4 is in unnamed module of loader 'MyClassLoader' @") ||
|
||||
!exception.contains("; java.lang.String is in module java.base of loader 'bootstrap')")) {
|
||||
throw new RuntimeException("Wrong message: " + exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class OriginalInner extends java.lang.Object {
|
||||
public int method(int left, int right) {
|
||||
return right;
|
||||
}
|
||||
}
|
||||
|
||||
class Derived extends java.lang.Object {
|
||||
public int method(int left, int right) {
|
||||
return right;
|
||||
|
@ -1,2 +1,2 @@
|
||||
java.lang.ClassCastException: jit.t.t113.kid1 cannot be cast to jit.t.t113.kid2
|
||||
java.lang.ClassCastException: class jit.t.t113.kid1 cannot be cast to class jit.t.t113.kid2 (jit.t.t113.kid1 and jit.t.t113.kid2 are in unnamed module of loader 'app')
|
||||
at jit.t.t113.t113.main(t113.java:59)
|
||||
|
Loading…
x
Reference in New Issue
Block a user