mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8199940: Print more information about class loaders in IllegalAccessErrors
Reviewed-by: lfoltan, mchung
This commit is contained in:
parent
1e4a26ceda
commit
cad47f4a03
10 changed files with 762 additions and 38 deletions
|
@ -4612,12 +4612,17 @@ static void check_super_class_access(const InstanceKlass* this_klass, TRAPS) {
|
||||||
InstanceKlass::cast(super),
|
InstanceKlass::cast(super),
|
||||||
vca_result);
|
vca_result);
|
||||||
if (msg == NULL) {
|
if (msg == NULL) {
|
||||||
|
bool same_module = (this_klass->module() == super->module());
|
||||||
Exceptions::fthrow(
|
Exceptions::fthrow(
|
||||||
THREAD_AND_LOCATION,
|
THREAD_AND_LOCATION,
|
||||||
vmSymbols::java_lang_IllegalAccessError(),
|
vmSymbols::java_lang_IllegalAccessError(),
|
||||||
"class %s cannot access its superclass %s",
|
"class %s cannot access its %ssuperclass %s (%s%s%s)",
|
||||||
this_klass->external_name(),
|
this_klass->external_name(),
|
||||||
super->external_name());
|
super->is_abstract() ? "abstract " : "",
|
||||||
|
super->external_name(),
|
||||||
|
(same_module) ? this_klass->joint_in_module_of_loader(super) : this_klass->class_in_module_of_loader(),
|
||||||
|
(same_module) ? "" : "; ",
|
||||||
|
(same_module) ? "" : super->class_in_module_of_loader());
|
||||||
} else {
|
} else {
|
||||||
// Add additional message content.
|
// Add additional message content.
|
||||||
Exceptions::fthrow(
|
Exceptions::fthrow(
|
||||||
|
@ -4646,12 +4651,16 @@ static void check_super_interface_access(const InstanceKlass* this_klass, TRAPS)
|
||||||
InstanceKlass::cast(k),
|
InstanceKlass::cast(k),
|
||||||
vca_result);
|
vca_result);
|
||||||
if (msg == NULL) {
|
if (msg == NULL) {
|
||||||
|
bool same_module = (this_klass->module() == k->module());
|
||||||
Exceptions::fthrow(
|
Exceptions::fthrow(
|
||||||
THREAD_AND_LOCATION,
|
THREAD_AND_LOCATION,
|
||||||
vmSymbols::java_lang_IllegalAccessError(),
|
vmSymbols::java_lang_IllegalAccessError(),
|
||||||
"class %s cannot access its superinterface %s",
|
"class %s cannot access its superinterface %s (%s%s%s)",
|
||||||
this_klass->external_name(),
|
this_klass->external_name(),
|
||||||
k->external_name());
|
k->external_name(),
|
||||||
|
(same_module) ? this_klass->joint_in_module_of_loader(k) : this_klass->class_in_module_of_loader(),
|
||||||
|
(same_module) ? "" : "; ",
|
||||||
|
(same_module) ? "" : k->class_in_module_of_loader());
|
||||||
} else {
|
} else {
|
||||||
// Add additional message content.
|
// Add additional message content.
|
||||||
Exceptions::fthrow(
|
Exceptions::fthrow(
|
||||||
|
|
|
@ -218,7 +218,7 @@ void CallInfo::verify() {
|
||||||
fatal("Unexpected call kind %d", call_kind());
|
fatal("Unexpected call kind %d", call_kind());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif //ASSERT
|
#endif // ASSERT
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
void CallInfo::print() {
|
void CallInfo::print() {
|
||||||
|
@ -294,7 +294,7 @@ void LinkResolver::check_klass_accessability(Klass* ref_klass, Klass* sel_klass,
|
||||||
base_klass = ObjArrayKlass::cast(sel_klass)->bottom_klass();
|
base_klass = ObjArrayKlass::cast(sel_klass)->bottom_klass();
|
||||||
}
|
}
|
||||||
// The element type could be a typeArray - we only need the access
|
// The element type could be a typeArray - we only need the access
|
||||||
// check if it is an reference to another class.
|
// check if it is a reference to another class.
|
||||||
if (!base_klass->is_instance_klass()) {
|
if (!base_klass->is_instance_klass()) {
|
||||||
return; // no relevant check to do
|
return; // no relevant check to do
|
||||||
}
|
}
|
||||||
|
@ -306,13 +306,17 @@ void LinkResolver::check_klass_accessability(Klass* ref_klass, Klass* sel_klass,
|
||||||
char* msg = Reflection::verify_class_access_msg(ref_klass,
|
char* msg = Reflection::verify_class_access_msg(ref_klass,
|
||||||
InstanceKlass::cast(base_klass),
|
InstanceKlass::cast(base_klass),
|
||||||
vca_result);
|
vca_result);
|
||||||
|
bool same_module = (base_klass->module() == ref_klass->module());
|
||||||
if (msg == NULL) {
|
if (msg == NULL) {
|
||||||
Exceptions::fthrow(
|
Exceptions::fthrow(
|
||||||
THREAD_AND_LOCATION,
|
THREAD_AND_LOCATION,
|
||||||
vmSymbols::java_lang_IllegalAccessError(),
|
vmSymbols::java_lang_IllegalAccessError(),
|
||||||
"failed to access class %s from class %s",
|
"failed to access class %s from class %s (%s%s%s)",
|
||||||
base_klass->external_name(),
|
base_klass->external_name(),
|
||||||
ref_klass->external_name());
|
ref_klass->external_name(),
|
||||||
|
(same_module) ? base_klass->joint_in_module_of_loader(ref_klass) : base_klass->class_in_module_of_loader(),
|
||||||
|
(same_module) ? "" : "; ",
|
||||||
|
(same_module) ? "" : ref_klass->class_in_module_of_loader());
|
||||||
} else {
|
} else {
|
||||||
// Use module specific message returned by verify_class_access_msg().
|
// Use module specific message returned by verify_class_access_msg().
|
||||||
Exceptions::fthrow(
|
Exceptions::fthrow(
|
||||||
|
@ -596,8 +600,11 @@ void LinkResolver::check_method_accessability(Klass* ref_klass,
|
||||||
Exceptions::fthrow(
|
Exceptions::fthrow(
|
||||||
THREAD_AND_LOCATION,
|
THREAD_AND_LOCATION,
|
||||||
vmSymbols::java_lang_IllegalAccessError(),
|
vmSymbols::java_lang_IllegalAccessError(),
|
||||||
"class %s tried to access method %s.%s%s (%s%s%s)",
|
"class %s tried to access %s%s%smethod %s.%s%s (%s%s%s)",
|
||||||
ref_klass->external_name(),
|
ref_klass->external_name(),
|
||||||
|
sel_method->is_abstract() ? "abstract " : "",
|
||||||
|
sel_method->is_protected() ? "protected " : "",
|
||||||
|
sel_method->is_private() ? "private " : "",
|
||||||
sel_klass->external_name(),
|
sel_klass->external_name(),
|
||||||
sel_method->name()->as_C_string(),
|
sel_method->name()->as_C_string(),
|
||||||
sel_method->signature()->as_C_string(),
|
sel_method->signature()->as_C_string(),
|
||||||
|
@ -927,14 +934,20 @@ void LinkResolver::check_field_accessability(Klass* ref_klass,
|
||||||
// Any existing exceptions that may have been thrown, for example LinkageErrors
|
// Any existing exceptions that may have been thrown, for example LinkageErrors
|
||||||
// from nest-host resolution, have been allowed to propagate.
|
// from nest-host resolution, have been allowed to propagate.
|
||||||
if (!can_access) {
|
if (!can_access) {
|
||||||
|
bool same_module = (sel_klass->module() == ref_klass->module());
|
||||||
ResourceMark rm(THREAD);
|
ResourceMark rm(THREAD);
|
||||||
Exceptions::fthrow(
|
Exceptions::fthrow(
|
||||||
THREAD_AND_LOCATION,
|
THREAD_AND_LOCATION,
|
||||||
vmSymbols::java_lang_IllegalAccessError(),
|
vmSymbols::java_lang_IllegalAccessError(),
|
||||||
"tried to access field %s.%s from class %s",
|
"class %s tried to access %s%sfield %s.%s (%s%s%s)",
|
||||||
|
ref_klass->external_name(),
|
||||||
|
fd.is_protected() ? "protected " : "",
|
||||||
|
fd.is_private() ? "private " : "",
|
||||||
sel_klass->external_name(),
|
sel_klass->external_name(),
|
||||||
fd.name()->as_C_string(),
|
fd.name()->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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -671,7 +671,7 @@ public class TestNestmateMembership {
|
||||||
static void test_NoHostInvoke() throws Throwable {
|
static void test_NoHostInvoke() throws Throwable {
|
||||||
System.out.println("Testing for missing nest-host attribute");
|
System.out.println("Testing for missing nest-host attribute");
|
||||||
String msg = "class TestNestmateMembership$Caller tried to access " +
|
String msg = "class TestNestmateMembership$Caller tried to access " +
|
||||||
"method TestNestmateMembership$TargetNoHost.m()V";
|
"private method TestNestmateMembership$TargetNoHost.m()V";
|
||||||
try {
|
try {
|
||||||
Caller.invokeTargetNoHost();
|
Caller.invokeTargetNoHost();
|
||||||
throw new Error("Missing IllegalAccessError: " + msg);
|
throw new Error("Missing IllegalAccessError: " + msg);
|
||||||
|
@ -698,7 +698,7 @@ public class TestNestmateMembership {
|
||||||
}
|
}
|
||||||
|
|
||||||
msg = "class TestNestmateMembership$CallerNoHost tried to access " +
|
msg = "class TestNestmateMembership$CallerNoHost tried to access " +
|
||||||
"method TestNestmateMembership$Target.m()V";
|
"private method TestNestmateMembership$Target.m()V";
|
||||||
try {
|
try {
|
||||||
CallerNoHost.invokeTarget();
|
CallerNoHost.invokeTarget();
|
||||||
throw new Error("Missing IllegalAccessError: " + msg);
|
throw new Error("Missing IllegalAccessError: " + msg);
|
||||||
|
@ -706,8 +706,8 @@ public class TestNestmateMembership {
|
||||||
catch (IllegalAccessError expected) {
|
catch (IllegalAccessError expected) {
|
||||||
check_expected(expected, msg);
|
check_expected(expected, msg);
|
||||||
}
|
}
|
||||||
msg = "class TestNestmateMembership$CallerNoHost tried to access method " +
|
msg = "class TestNestmateMembership$CallerNoHost tried to access private " +
|
||||||
"TestNestmateMembership$TargetNoHost.m()V";
|
"method TestNestmateMembership$TargetNoHost.m()V";
|
||||||
try {
|
try {
|
||||||
CallerNoHost.invokeTargetNoHost();
|
CallerNoHost.invokeTargetNoHost();
|
||||||
throw new Error("Missing IllegalAccessError: " + msg);
|
throw new Error("Missing IllegalAccessError: " + msg);
|
||||||
|
@ -949,8 +949,8 @@ public class TestNestmateMembership {
|
||||||
|
|
||||||
static void test_NoHostConstruct() throws Throwable {
|
static void test_NoHostConstruct() throws Throwable {
|
||||||
System.out.println("Testing for missing nest-host attribute");
|
System.out.println("Testing for missing nest-host attribute");
|
||||||
String msg = "class TestNestmateMembership$Caller tried to access method " +
|
String msg = "class TestNestmateMembership$Caller tried to access private " +
|
||||||
"TestNestmateMembership$TargetNoHost.<init>()V";
|
"method TestNestmateMembership$TargetNoHost.<init>()V";
|
||||||
try {
|
try {
|
||||||
Caller.newTargetNoHost();
|
Caller.newTargetNoHost();
|
||||||
throw new Error("Missing IncompatibleClassChangeError: " + msg);
|
throw new Error("Missing IncompatibleClassChangeError: " + msg);
|
||||||
|
@ -976,8 +976,8 @@ public class TestNestmateMembership {
|
||||||
check_expected(expected, msg);
|
check_expected(expected, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
msg = "class TestNestmateMembership$CallerNoHost tried to access method " +
|
msg = "class TestNestmateMembership$CallerNoHost tried to access private " +
|
||||||
"TestNestmateMembership$Target.<init>()V";
|
"method TestNestmateMembership$Target.<init>()V";
|
||||||
try {
|
try {
|
||||||
CallerNoHost.newTarget();
|
CallerNoHost.newTarget();
|
||||||
throw new Error("Missing IncompatibleClassChangeError: " + msg);
|
throw new Error("Missing IncompatibleClassChangeError: " + msg);
|
||||||
|
@ -985,8 +985,8 @@ public class TestNestmateMembership {
|
||||||
catch (IncompatibleClassChangeError expected) {
|
catch (IncompatibleClassChangeError expected) {
|
||||||
check_expected(expected, msg);
|
check_expected(expected, msg);
|
||||||
}
|
}
|
||||||
msg = "class TestNestmateMembership$CallerNoHost tried to access method " +
|
msg = "class TestNestmateMembership$CallerNoHost tried to access private " +
|
||||||
"TestNestmateMembership$TargetNoHost.<init>()V";
|
"method TestNestmateMembership$TargetNoHost.<init>()V";
|
||||||
try {
|
try {
|
||||||
CallerNoHost.newTargetNoHost();
|
CallerNoHost.newTargetNoHost();
|
||||||
throw new Error("Missing IncompatibleClassChangeError: " + msg);
|
throw new Error("Missing IncompatibleClassChangeError: " + msg);
|
||||||
|
@ -1220,8 +1220,8 @@ public class TestNestmateMembership {
|
||||||
|
|
||||||
static void test_NoHostGetField() throws Throwable {
|
static void test_NoHostGetField() throws Throwable {
|
||||||
System.out.println("Testing for missing nest-host attribute");
|
System.out.println("Testing for missing nest-host attribute");
|
||||||
String msg = "tried to access field TestNestmateMembership$TargetNoHost.f" +
|
String msg = "class TestNestmateMembership$Caller tried to access private " +
|
||||||
" from class TestNestmateMembership$Caller";
|
"field TestNestmateMembership$TargetNoHost.f";
|
||||||
try {
|
try {
|
||||||
Caller.getFieldTargetNoHost();
|
Caller.getFieldTargetNoHost();
|
||||||
throw new Error("Missing IncompatibleClassChangeError: " + msg);
|
throw new Error("Missing IncompatibleClassChangeError: " + msg);
|
||||||
|
@ -1247,8 +1247,8 @@ public class TestNestmateMembership {
|
||||||
check_expected(expected, msg);
|
check_expected(expected, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
msg = "tried to access field TestNestmateMembership$Target.f" +
|
msg = "class TestNestmateMembership$CallerNoHost tried to access private " +
|
||||||
" from class TestNestmateMembership$CallerNoHost";
|
"field TestNestmateMembership$Target.f";
|
||||||
try {
|
try {
|
||||||
CallerNoHost.getFieldTarget();
|
CallerNoHost.getFieldTarget();
|
||||||
throw new Error("Missing IncompatibleClassChangeError: " + msg);
|
throw new Error("Missing IncompatibleClassChangeError: " + msg);
|
||||||
|
@ -1256,8 +1256,8 @@ public class TestNestmateMembership {
|
||||||
catch (IncompatibleClassChangeError expected) {
|
catch (IncompatibleClassChangeError expected) {
|
||||||
check_expected(expected, msg);
|
check_expected(expected, msg);
|
||||||
}
|
}
|
||||||
msg = "tried to access field TestNestmateMembership$TargetNoHost.f" +
|
msg = "class TestNestmateMembership$CallerNoHost tried to access private " +
|
||||||
" from class TestNestmateMembership$CallerNoHost";
|
"field TestNestmateMembership$TargetNoHost.f";
|
||||||
try {
|
try {
|
||||||
CallerNoHost.getFieldTargetNoHost();
|
CallerNoHost.getFieldTargetNoHost();
|
||||||
throw new Error("Missing IncompatibleClassChangeError: " + msg);
|
throw new Error("Missing IncompatibleClassChangeError: " + msg);
|
||||||
|
@ -1485,8 +1485,8 @@ public class TestNestmateMembership {
|
||||||
|
|
||||||
static void test_NoHostPutField() throws Throwable {
|
static void test_NoHostPutField() throws Throwable {
|
||||||
System.out.println("Testing for missing nest-host attribute");
|
System.out.println("Testing for missing nest-host attribute");
|
||||||
String msg = "tried to access field TestNestmateMembership$TargetNoHost.f" +
|
String msg = "class TestNestmateMembership$Caller tried to access private " +
|
||||||
" from class TestNestmateMembership$Caller";
|
"field TestNestmateMembership$TargetNoHost.f";
|
||||||
try {
|
try {
|
||||||
Caller.putFieldTargetNoHost();
|
Caller.putFieldTargetNoHost();
|
||||||
throw new Error("Missing IncompatibleClassChangeError: " + msg);
|
throw new Error("Missing IncompatibleClassChangeError: " + msg);
|
||||||
|
@ -1512,8 +1512,8 @@ public class TestNestmateMembership {
|
||||||
check_expected(expected, msg);
|
check_expected(expected, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
msg = "tried to access field TestNestmateMembership$Target.f" +
|
msg = "class TestNestmateMembership$CallerNoHost tried to access private " +
|
||||||
" from class TestNestmateMembership$CallerNoHost";
|
"field TestNestmateMembership$Target.f";
|
||||||
try {
|
try {
|
||||||
CallerNoHost.putFieldTarget();
|
CallerNoHost.putFieldTarget();
|
||||||
throw new Error("Missing IncompatibleClassChangeError: " + msg);
|
throw new Error("Missing IncompatibleClassChangeError: " + msg);
|
||||||
|
@ -1521,8 +1521,8 @@ public class TestNestmateMembership {
|
||||||
catch (IncompatibleClassChangeError expected) {
|
catch (IncompatibleClassChangeError expected) {
|
||||||
check_expected(expected, msg);
|
check_expected(expected, msg);
|
||||||
}
|
}
|
||||||
msg = "tried to access field TestNestmateMembership$TargetNoHost.f" +
|
msg = "class TestNestmateMembership$CallerNoHost tried to access private " +
|
||||||
" from class TestNestmateMembership$CallerNoHost";
|
"field TestNestmateMembership$TargetNoHost.f";
|
||||||
try {
|
try {
|
||||||
CallerNoHost.putFieldTargetNoHost();
|
CallerNoHost.putFieldTargetNoHost();
|
||||||
throw new Error("Missing IncompatibleClassChangeError: " + msg);
|
throw new Error("Missing IncompatibleClassChangeError: " + msg);
|
||||||
|
|
|
@ -51,7 +51,7 @@ public class TestConstructorHierarchy {
|
||||||
throw new Error("Unexpected construction of ExternalSuper");
|
throw new Error("Unexpected construction of ExternalSuper");
|
||||||
}
|
}
|
||||||
catch (IllegalAccessError iae) {
|
catch (IllegalAccessError iae) {
|
||||||
if (iae.getMessage().contains("class TestConstructorHierarchy tried to access method ExternalSuper.<init>()V")) {
|
if (iae.getMessage().contains("class TestConstructorHierarchy tried to access private method ExternalSuper.<init>()V")) {
|
||||||
System.out.println("Got expected exception constructing ExternalSuper: " + iae);
|
System.out.println("Got expected exception constructing ExternalSuper: " + iae);
|
||||||
}
|
}
|
||||||
else throw new Error("Unexpected IllegalAccessError: " + iae);
|
else throw new Error("Unexpected IllegalAccessError: " + iae);
|
||||||
|
@ -61,7 +61,7 @@ public class TestConstructorHierarchy {
|
||||||
throw new Error("Unexpected construction of NestedA and supers");
|
throw new Error("Unexpected construction of NestedA and supers");
|
||||||
}
|
}
|
||||||
catch (IllegalAccessError iae) {
|
catch (IllegalAccessError iae) {
|
||||||
if (iae.getMessage().contains("class TestConstructorHierarchy$NestedA tried to access method ExternalSuper.<init>()V")) {
|
if (iae.getMessage().contains("class TestConstructorHierarchy$NestedA tried to access private method ExternalSuper.<init>()V")) {
|
||||||
System.out.println("Got expected exception constructing NestedA: " + iae);
|
System.out.println("Got expected exception constructing NestedA: " + iae);
|
||||||
}
|
}
|
||||||
else throw new Error("Unexpected IllegalAccessError: " + iae);
|
else throw new Error("Unexpected IllegalAccessError: " + iae);
|
||||||
|
@ -71,7 +71,7 @@ public class TestConstructorHierarchy {
|
||||||
throw new Error("Unexpected construction of ExternalSub");
|
throw new Error("Unexpected construction of ExternalSub");
|
||||||
}
|
}
|
||||||
catch (IllegalAccessError iae) {
|
catch (IllegalAccessError iae) {
|
||||||
if (iae.getMessage().contains("class ExternalSub tried to access method TestConstructorHierarchy$NestedA.<init>()V")) {
|
if (iae.getMessage().contains("class ExternalSub tried to access private method TestConstructorHierarchy$NestedA.<init>()V")) {
|
||||||
System.out.println("Got expected exception constructing ExternalSub: " + iae);
|
System.out.println("Got expected exception constructing ExternalSub: " + iae);
|
||||||
}
|
}
|
||||||
else throw new Error("Unexpected IllegalAccessError: " + iae);
|
else throw new Error("Unexpected IllegalAccessError: " + iae);
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 by SAP AG, Walldorf, Germany.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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 test;
|
||||||
|
|
||||||
|
public class IAE78_A {
|
||||||
|
|
||||||
|
static Object f = new Object();
|
||||||
|
|
||||||
|
IAE78_A() {
|
||||||
|
// Nothing to do.
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* Copyright (c) 2018 SAP SE. 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.
|
||||||
|
*
|
||||||
|
* 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 test;
|
||||||
|
|
||||||
|
public class IAE78_B {
|
||||||
|
|
||||||
|
public static void create() {
|
||||||
|
new IAE78_A();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void access() {
|
||||||
|
IAE78_A.f.hashCode();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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 test;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public class IAE_Loader1 extends ClassLoader {
|
||||||
|
|
||||||
|
private final Set<String> names = new HashSet<>();
|
||||||
|
|
||||||
|
public IAE_Loader1(String name, String[] names) {
|
||||||
|
super(name, ClassLoader.getSystemClassLoader());
|
||||||
|
for (String n : names) this.names.add(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
|
||||||
|
if (!names.contains(name)) {
|
||||||
|
return super.loadClass(name, resolve);
|
||||||
|
}
|
||||||
|
String filename = name.replace('.', '/') + ".class";
|
||||||
|
Class<?> result = null;
|
||||||
|
try (InputStream data = getResourceAsStream(filename)) {
|
||||||
|
if (data == null) {
|
||||||
|
throw new ClassNotFoundException();
|
||||||
|
}
|
||||||
|
try (ByteArrayOutputStream buffer = new ByteArrayOutputStream()) {
|
||||||
|
byte[] bytes = data.readAllBytes();
|
||||||
|
result = defineClass(name, bytes, 0, bytes.length);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new ClassNotFoundException("Error reading class file", e);
|
||||||
|
}
|
||||||
|
if (resolve) resolveClass(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,166 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 by SAP AG, Walldorf, Germany.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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 test;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.security.SecureClassLoader;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a class loader which can load the same classes as another class loader.
|
||||||
|
* <p>
|
||||||
|
* This is mainly useful for tests when you want to load a class, but do it with a class
|
||||||
|
* loader you can dispose. The clone loader just asks the loader to be cloned to get
|
||||||
|
* the bytecodes, but defines the class itself.
|
||||||
|
* <p>
|
||||||
|
* Additionally you can specify a set of classes the loader should not be able to load.
|
||||||
|
*/
|
||||||
|
public class IAE_Loader2 extends SecureClassLoader {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class loaded to clone.
|
||||||
|
*/
|
||||||
|
private final ClassLoader toClone;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The strings we cannot load.
|
||||||
|
*/
|
||||||
|
private final HashSet<String> notLoadable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The strings we just delegate.
|
||||||
|
*/
|
||||||
|
private final HashSet<String> simpleDelegate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a class loader which can load the same classes as the loader which
|
||||||
|
* loaded the <code>IAE_Loader2</code> class itself.
|
||||||
|
* <p>
|
||||||
|
* Only the classes which are loadable by the 'parent' loader are delegated to that
|
||||||
|
* loader (to make it possible mix classes).
|
||||||
|
*
|
||||||
|
* @param name the name of the class loader.
|
||||||
|
* @param parent the parent loader which is first asked to load a class.
|
||||||
|
* @param toClone the class loader to mimic. The clone class loader will be able to
|
||||||
|
* load the same classes as the 'toClone' loader.
|
||||||
|
* @param notLoadable The classes we should not be able to load via this loader.
|
||||||
|
* @param simpleDelegate The names of the classes for which we simply delegate.
|
||||||
|
*/
|
||||||
|
public IAE_Loader2(String name, ClassLoader parent, ClassLoader toClone,
|
||||||
|
String[] notLoadable, String[] simpleDelegate) {
|
||||||
|
super(name, parent);
|
||||||
|
|
||||||
|
this.toClone = toClone;
|
||||||
|
this.notLoadable = Arrays.stream(notLoadable).collect(Collectors.toCollection(HashSet<String>::new));
|
||||||
|
this.simpleDelegate = Arrays.stream(simpleDelegate).collect(Collectors.toCollection(HashSet<String>::new));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see java.lang.ClassLoader#findClass(java.lang.String)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected Class<?> findClass(String name) throws ClassNotFoundException {
|
||||||
|
if (notLoadable.contains(name)) {
|
||||||
|
throw new ClassNotFoundException("The clone class loader explicitely " +
|
||||||
|
"didn't found the class");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (simpleDelegate.contains(name)) {
|
||||||
|
return toClone.loadClass(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We just ask the wrapper class loader to find the resource for us
|
||||||
|
URL res = toClone.getResource(name.replace('.', '/') + ".class");
|
||||||
|
|
||||||
|
if (res == null) {
|
||||||
|
throw new ClassNotFoundException(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
InputStream is = res.openStream();
|
||||||
|
byte[] code = readStreamIntoBuffer(is, 8192);
|
||||||
|
is.close();
|
||||||
|
return defineClass(name, code, 0, code.length);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new ClassNotFoundException(name, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads all data of a stream into a byte array. The method allocates as
|
||||||
|
* much memory as necessary to put the whole data into that byte
|
||||||
|
* array. The data is read in chunks of <code>chunkSize</code>
|
||||||
|
* chunks.<br><br>
|
||||||
|
* <b>Implementation Note: </b> The data is read in chunks of
|
||||||
|
* <code>chunkSize</code> bytes. The data is copied to the result
|
||||||
|
* array. The memory consumption at the end of the reading is
|
||||||
|
* <code>2 x [size of resulting array] + chunkSize</code>.
|
||||||
|
*
|
||||||
|
* @param is the stream to read the data from
|
||||||
|
* @param chunkSize the size of the chunks the data should be read in
|
||||||
|
* @return the <b>whole</b> data of the stream read into an byte array
|
||||||
|
* @throws IllegalArgumentException if chunkSize <= 0
|
||||||
|
* @throws NullPointerException if is == null
|
||||||
|
* @throws IOException thrown if the provided stream encounters IO problems
|
||||||
|
*/
|
||||||
|
public static byte[] readStreamIntoBuffer(InputStream is, int chunkSize)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
|
// Check preconditions.
|
||||||
|
if (chunkSize <= 0) {
|
||||||
|
throw new IllegalArgumentException("chunkSize <= 0");
|
||||||
|
}
|
||||||
|
else if (is == null) {
|
||||||
|
throw new NullPointerException("is is null");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Temporary buffer for read operations and result buffer.
|
||||||
|
byte[] tempBuffer = new byte[chunkSize];
|
||||||
|
byte[] buffer = new byte[0];
|
||||||
|
|
||||||
|
int bytesRead = 0; // bytes actual read
|
||||||
|
int oldSize = 0; // size of the resulting buffer
|
||||||
|
|
||||||
|
while ((bytesRead = is.read(tempBuffer)) > 0) {
|
||||||
|
|
||||||
|
// Temporary reference to the buffer for the copy operation.
|
||||||
|
byte[] oldBuffer = buffer;
|
||||||
|
|
||||||
|
// Create a new buffer with the size needed and copy data.
|
||||||
|
buffer = new byte[oldSize + bytesRead];
|
||||||
|
System.arraycopy(oldBuffer, 0, buffer, 0, oldBuffer.length);
|
||||||
|
|
||||||
|
// Copy the new data.
|
||||||
|
System.arraycopy(tempBuffer, 0, buffer, oldSize, bytesRead);
|
||||||
|
oldSize += bytesRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,405 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* Copyright (c) 2018 SAP SE. 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.
|
||||||
|
*
|
||||||
|
* 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 messages of IllegalAccessError.
|
||||||
|
* @modules java.base/java.lang:open
|
||||||
|
* java.base/jdk.internal.org.objectweb.asm
|
||||||
|
* @compile IAE_Loader1.java IAE_Loader2.java IAE78_A.java IAE78_B.java
|
||||||
|
* IllegalAccessErrorTest.java
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. test.IllegalAccessErrorTest
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Put this test into a package so we see qualified class names in
|
||||||
|
// the error messages. Verify that classes are printed with '.' instead
|
||||||
|
// of '/'.
|
||||||
|
package test;
|
||||||
|
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
import java.lang.invoke.MethodHandles.Lookup;
|
||||||
|
import static java.lang.invoke.MethodHandles.*;
|
||||||
|
import static java.lang.invoke.MethodHandles.Lookup.*;
|
||||||
|
import java.security.*;
|
||||||
|
|
||||||
|
import jdk.internal.org.objectweb.asm.ClassWriter;
|
||||||
|
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||||
|
import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
||||||
|
|
||||||
|
import test.*;
|
||||||
|
|
||||||
|
abstract public class IllegalAccessErrorTest {
|
||||||
|
|
||||||
|
// interface
|
||||||
|
private static String expectedErrorMessage1a_1 =
|
||||||
|
"class test.IAE1_B cannot access its superinterface test.IAE1_A " +
|
||||||
|
"(test.IAE1_B is in unnamed module of loader test.IAE_Loader1 @";
|
||||||
|
private static String expectedErrorMessage1a_2 =
|
||||||
|
"; test.IAE1_A is in unnamed module of loader 'app')";
|
||||||
|
private static String expectedErrorMessage1b_1 =
|
||||||
|
"class test.IAE1_B cannot access its superinterface test.IAE1_A " +
|
||||||
|
"(test.IAE1_B is in unnamed module of loader 'someCLName1' @";
|
||||||
|
private static String expectedErrorMessage1b_2 =
|
||||||
|
"; test.IAE1_A is in unnamed module of loader 'app')";
|
||||||
|
|
||||||
|
// abstract class
|
||||||
|
private static String expectedErrorMessage2_1 =
|
||||||
|
"class test.IAE2_B cannot access its abstract superclass test.IAE2_A " +
|
||||||
|
"(test.IAE2_B is in unnamed module of loader 'someCLName2' @";
|
||||||
|
private static String expectedErrorMessage2_2 =
|
||||||
|
"; test.IAE2_A is in unnamed module of loader 'app')";
|
||||||
|
|
||||||
|
// class
|
||||||
|
private static String expectedErrorMessage3_1 =
|
||||||
|
"class test.IAE3_B cannot access its superclass test.IAE3_A " +
|
||||||
|
"(test.IAE3_B is in unnamed module of loader 'someCLName3' @";
|
||||||
|
private static String expectedErrorMessage3_2 =
|
||||||
|
"; test.IAE3_A is in unnamed module of loader 'app')";
|
||||||
|
|
||||||
|
public static void test123(String loaderName,
|
||||||
|
String expectedErrorMessage_1,
|
||||||
|
String expectedErrorMessage_2,
|
||||||
|
String testClass) throws Exception {
|
||||||
|
String[] classNames = { testClass };
|
||||||
|
// Some classes under a new Loader.
|
||||||
|
ClassLoader l = new IAE_Loader1(loaderName, classNames);
|
||||||
|
|
||||||
|
try {
|
||||||
|
l.loadClass(testClass);
|
||||||
|
throw new RuntimeException("Expected IllegalAccessError was not thrown.");
|
||||||
|
} catch (IllegalAccessError iae) {
|
||||||
|
String errorMsg = iae.getMessage();
|
||||||
|
if (!(errorMsg.contains(expectedErrorMessage_1) &&
|
||||||
|
errorMsg.contains(expectedErrorMessage_2))) {
|
||||||
|
System.out.println("Expected: " + expectedErrorMessage_1 + "@id " + expectedErrorMessage_2 +"\n" +
|
||||||
|
"but got: " + errorMsg);
|
||||||
|
throw new RuntimeException("Wrong error message of IllegalAccessError.");
|
||||||
|
} else {
|
||||||
|
System.out.println("Passed with message: " + errorMsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate a class file with the given class name. The class implements Runnable
|
||||||
|
// with a run method to invokestatic the given targetClass/targetMethod.
|
||||||
|
static byte[] iae4_generateRunner(String className,
|
||||||
|
String targetClass,
|
||||||
|
String targetMethod) throws Exception {
|
||||||
|
|
||||||
|
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS
|
||||||
|
+ ClassWriter.COMPUTE_FRAMES);
|
||||||
|
cw.visit(V9,
|
||||||
|
ACC_PUBLIC + ACC_SUPER,
|
||||||
|
className.replace(".", "/"),
|
||||||
|
null,
|
||||||
|
"java/lang/Object",
|
||||||
|
new String[] { "java/lang/Runnable" });
|
||||||
|
|
||||||
|
// <init>
|
||||||
|
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
|
||||||
|
mv.visitVarInsn(ALOAD, 0);
|
||||||
|
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
|
||||||
|
mv.visitInsn(RETURN);
|
||||||
|
mv.visitMaxs(0, 0);
|
||||||
|
mv.visitEnd();
|
||||||
|
|
||||||
|
// run()
|
||||||
|
String tc = targetClass.replace(".", "/");
|
||||||
|
mv = cw.visitMethod(ACC_PUBLIC, "run", "()V", null, null);
|
||||||
|
mv.visitMethodInsn(INVOKESTATIC, tc, targetMethod, "()V", false);
|
||||||
|
mv.visitInsn(RETURN);
|
||||||
|
mv.visitMaxs(0, 0);
|
||||||
|
mv.visitEnd();
|
||||||
|
|
||||||
|
cw.visitEnd();
|
||||||
|
return cw.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private method that should raise IllegalAccessError when called.
|
||||||
|
private static void iae4_m() { }
|
||||||
|
|
||||||
|
private static String expectedErrorMessage4 =
|
||||||
|
"class test.Runner4 tried to access private method test.IllegalAccessErrorTest.iae4_m()V " +
|
||||||
|
"(test.Runner4 and test.IllegalAccessErrorTest are in unnamed module of loader 'app')";
|
||||||
|
|
||||||
|
// Test according to java/lang/invoke/DefineClassTest.java
|
||||||
|
public static void test4_privateMethod() throws Exception {
|
||||||
|
final String THIS_PACKAGE = IllegalAccessErrorTest.class.getPackageName();
|
||||||
|
final String THIS_CLASS = IllegalAccessErrorTest.class.getName();
|
||||||
|
final String CLASS_NAME = THIS_PACKAGE + ".Runner4";
|
||||||
|
Lookup lookup = lookup();
|
||||||
|
|
||||||
|
// private
|
||||||
|
byte[] classBytes = iae4_generateRunner(CLASS_NAME, THIS_CLASS, "iae4_m");
|
||||||
|
Class<?> clazz = lookup.defineClass(classBytes);
|
||||||
|
Runnable r = (Runnable) clazz.getDeclaredConstructor().newInstance();
|
||||||
|
try {
|
||||||
|
r.run();
|
||||||
|
throw new RuntimeException("Expected IllegalAccessError was not thrown.");
|
||||||
|
} catch (IllegalAccessError exc) {
|
||||||
|
String errorMsg = exc.getMessage();
|
||||||
|
if (!errorMsg.equals(expectedErrorMessage4)) {
|
||||||
|
System.out.println("Expected: " + expectedErrorMessage4 + "\n" +
|
||||||
|
"but got: " + errorMsg);
|
||||||
|
throw new RuntimeException("Wrong error message of IllegalAccessError.");
|
||||||
|
}
|
||||||
|
System.out.println("Passed with message: " + errorMsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate a class file with the given class name. The class implements Runnable
|
||||||
|
// with a run method to invokestatic the given targetClass/targetField.
|
||||||
|
static byte[] iae5_generateRunner(String className,
|
||||||
|
String targetClass,
|
||||||
|
String targetField) throws Exception {
|
||||||
|
|
||||||
|
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS
|
||||||
|
+ ClassWriter.COMPUTE_FRAMES);
|
||||||
|
cw.visit(V9,
|
||||||
|
ACC_PUBLIC + ACC_SUPER,
|
||||||
|
className.replace(".", "/"),
|
||||||
|
null,
|
||||||
|
"java/lang/Object",
|
||||||
|
new String[] { "java/lang/Runnable" });
|
||||||
|
|
||||||
|
// <init>
|
||||||
|
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
|
||||||
|
mv.visitVarInsn(ALOAD, 0);
|
||||||
|
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
|
||||||
|
mv.visitInsn(RETURN);
|
||||||
|
mv.visitMaxs(0, 0);
|
||||||
|
mv.visitEnd();
|
||||||
|
|
||||||
|
// run()
|
||||||
|
String tc = targetClass.replace(".", "/");
|
||||||
|
mv = cw.visitMethod(ACC_PUBLIC, "run", "()V", null, null);
|
||||||
|
mv.visitFieldInsn(GETSTATIC, tc, targetField, "I");
|
||||||
|
mv.visitInsn(RETURN);
|
||||||
|
mv.visitMaxs(0, 0);
|
||||||
|
mv.visitEnd();
|
||||||
|
|
||||||
|
cw.visitEnd();
|
||||||
|
return cw.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private field that should raise IllegalAccessError when accessed.
|
||||||
|
private static int iae5_f = 77;
|
||||||
|
|
||||||
|
private static String expectedErrorMessage5 =
|
||||||
|
"class test.Runner5 tried to access private field test.IllegalAccessErrorTest.iae5_f " +
|
||||||
|
"(test.Runner5 and test.IllegalAccessErrorTest are in unnamed module of loader 'app')";
|
||||||
|
|
||||||
|
// Test according to java/lang/invoke/DefineClassTest.java
|
||||||
|
public static void test5_privateField() throws Exception {
|
||||||
|
final String THIS_PACKAGE = IllegalAccessErrorTest.class.getPackageName();
|
||||||
|
final String THIS_CLASS = IllegalAccessErrorTest.class.getName();
|
||||||
|
final String CLASS_NAME = THIS_PACKAGE + ".Runner5";
|
||||||
|
Lookup lookup = lookup();
|
||||||
|
|
||||||
|
// private
|
||||||
|
byte[] classBytes = iae5_generateRunner(CLASS_NAME, THIS_CLASS, "iae5_f");
|
||||||
|
Class<?> clazz = lookup.defineClass(classBytes);
|
||||||
|
Runnable r = (Runnable) clazz.getDeclaredConstructor().newInstance();
|
||||||
|
try {
|
||||||
|
r.run();
|
||||||
|
throw new RuntimeException("Expected IllegalAccessError was not thrown.");
|
||||||
|
} catch (IllegalAccessError exc) {
|
||||||
|
String errorMsg = exc.getMessage();
|
||||||
|
if (!errorMsg.equals(expectedErrorMessage5)) {
|
||||||
|
System.out.println("Expected: " + expectedErrorMessage5 + "\n" +
|
||||||
|
"but got: " + errorMsg);
|
||||||
|
throw new RuntimeException("Wrong error message of IllegalAccessError.");
|
||||||
|
}
|
||||||
|
System.out.println("Passed with message: " + errorMsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String expectedErrorMessage6 =
|
||||||
|
"failed to access class test.IAE6_A from class test.IAE6_B " +
|
||||||
|
"(test.IAE6_A is in unnamed module of loader 'app'; test.IAE6_B is in unnamed module of loader 'test6_class_CL' @";
|
||||||
|
|
||||||
|
public static void test6_class() throws Exception {
|
||||||
|
ClassLoader base = IllegalAccessErrorTest.class.getClassLoader();
|
||||||
|
IAE_Loader2 loader = new IAE_Loader2("test6_class_CL", base.getParent(), base, new String[0],
|
||||||
|
new String[] { IAE6_A.class.getName() });
|
||||||
|
Class<?> cl = loader.loadClass(IAE6_B.class.getName());
|
||||||
|
Method m = cl.getDeclaredMethod("create", new Class[0]);
|
||||||
|
m.setAccessible(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
m.invoke(null, new Object[0]);
|
||||||
|
throw new RuntimeException("Expected IllegalAccessError was not thrown.");
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
IllegalAccessError iae = (IllegalAccessError) e.getCause();
|
||||||
|
String errorMsg = iae.getMessage();
|
||||||
|
if (!errorMsg.contains(expectedErrorMessage6)) {
|
||||||
|
System.out.println("Expected: " + expectedErrorMessage6 + "id)\n" +
|
||||||
|
"but got: " + errorMsg);
|
||||||
|
throw new RuntimeException("Wrong error message of IllegalAccessError.");
|
||||||
|
}
|
||||||
|
System.out.println("Passed with message: " + errorMsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String expectedErrorMessage7_1 =
|
||||||
|
"class test.IAE78_B tried to access method test.IAE78_A.<init>()V " +
|
||||||
|
"(test.IAE78_B is in unnamed module of loader 'test7_method_CL' @";
|
||||||
|
private static String expectedErrorMessage7_2 =
|
||||||
|
"; test.IAE78_A is in unnamed module of loader 'app')";
|
||||||
|
|
||||||
|
// Similar to test4.
|
||||||
|
public static void test7_method() throws Exception {
|
||||||
|
ClassLoader base = IllegalAccessErrorTest.class.getClassLoader();
|
||||||
|
IAE_Loader2 loader = new IAE_Loader2("test7_method_CL", base.getParent(), base, new String[0],
|
||||||
|
new String[] {IAE78_A.class.getName()});
|
||||||
|
Class<?> cl = loader.loadClass(IAE78_B.class.getName());
|
||||||
|
Method m = cl.getDeclaredMethod("create", new Class[0]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
m.invoke(null, new Object[0]);
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
IllegalAccessError iae = (IllegalAccessError) e.getCause();
|
||||||
|
String errorMsg = iae.getMessage();
|
||||||
|
if (!(errorMsg.contains(expectedErrorMessage7_1) &&
|
||||||
|
errorMsg.contains(expectedErrorMessage7_2))) {
|
||||||
|
System.out.println("Expected: " + expectedErrorMessage7_1 + "id" + expectedErrorMessage7_2 + "\n" +
|
||||||
|
"but got: " + errorMsg);
|
||||||
|
throw new RuntimeException("Wrong error message of IllegalAccessError.");
|
||||||
|
}
|
||||||
|
System.out.println("Passed with message: " + errorMsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String expectedErrorMessage8_1 =
|
||||||
|
"class test.IAE78_B tried to access field test.IAE78_A.f " +
|
||||||
|
"(test.IAE78_B is in unnamed module of loader 'test8_field_CL' @";
|
||||||
|
private static String expectedErrorMessage8_2 =
|
||||||
|
"; test.IAE78_A is in unnamed module of loader 'app')";
|
||||||
|
|
||||||
|
// Similar to test5.
|
||||||
|
public static void test8_field() throws Exception {
|
||||||
|
ClassLoader base = IllegalAccessErrorTest.class.getClassLoader();
|
||||||
|
IAE_Loader2 loader = new IAE_Loader2("test8_field_CL", base.getParent(), base, new String[0],
|
||||||
|
new String[] { IAE78_A.class.getName() });
|
||||||
|
Class<?> cl = loader.loadClass(IAE78_B.class.getName());
|
||||||
|
Method m = cl.getDeclaredMethod("access", new Class[0]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
m.invoke(null, new Object[0]);
|
||||||
|
}
|
||||||
|
catch (InvocationTargetException e) {
|
||||||
|
IllegalAccessError iae = (IllegalAccessError) e.getCause();
|
||||||
|
String errorMsg = iae.getMessage();
|
||||||
|
if (!(errorMsg.contains(expectedErrorMessage8_1) &&
|
||||||
|
errorMsg.contains(expectedErrorMessage8_2))) {
|
||||||
|
System.out.println("Expected: " + expectedErrorMessage8_1 + "id" + expectedErrorMessage8_2 + "\n" +
|
||||||
|
"but got: " + errorMsg);
|
||||||
|
throw new RuntimeException("Wrong error message of IllegalAccessError.");
|
||||||
|
}
|
||||||
|
System.out.println("Passed with message: " + errorMsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
test123(null, expectedErrorMessage1a_1, expectedErrorMessage1a_2, "test.IAE1_B"); // interface
|
||||||
|
test123("someCLName1", expectedErrorMessage1b_1, expectedErrorMessage1b_2, "test.IAE1_B"); // interface
|
||||||
|
test123("someCLName2", expectedErrorMessage2_1, expectedErrorMessage2_2, "test.IAE2_B"); // abstract class
|
||||||
|
test123("someCLName3", expectedErrorMessage3_1, expectedErrorMessage3_2, "test.IAE3_B"); // class
|
||||||
|
test4_privateMethod();
|
||||||
|
test5_privateField();
|
||||||
|
test6_class();
|
||||||
|
test7_method();
|
||||||
|
test8_field();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Class hierarchies for test1.
|
||||||
|
interface IAE1_A {
|
||||||
|
public IAE1_D gen();
|
||||||
|
}
|
||||||
|
|
||||||
|
class IAE1_B implements IAE1_A {
|
||||||
|
public IAE1_D gen() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class IAE1_C {
|
||||||
|
}
|
||||||
|
|
||||||
|
class IAE1_D extends IAE1_C {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Class hierarchies for test2.
|
||||||
|
abstract class IAE2_A {
|
||||||
|
abstract public IAE2_D gen();
|
||||||
|
}
|
||||||
|
|
||||||
|
class IAE2_B extends IAE2_A {
|
||||||
|
public IAE2_D gen() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class IAE2_C {
|
||||||
|
}
|
||||||
|
|
||||||
|
class IAE2_D extends IAE2_C {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Class hierarchies for test3.
|
||||||
|
class IAE3_A {
|
||||||
|
public IAE3_D gen() {
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class IAE3_B extends IAE3_A {
|
||||||
|
public IAE3_D gen() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class IAE3_C {
|
||||||
|
}
|
||||||
|
|
||||||
|
class IAE3_D extends IAE3_C {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Class hierarchies for test6.
|
||||||
|
class IAE6_A {
|
||||||
|
IAE6_A() {
|
||||||
|
// Nothing to do.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class IAE6_B {
|
||||||
|
public static void create() {
|
||||||
|
new IAE6_A();
|
||||||
|
}
|
||||||
|
}
|
|
@ -103,9 +103,10 @@ public class ExpQualToM1PrivateMethodIAE {
|
||||||
String message = e.getMessage();
|
String message = e.getMessage();
|
||||||
System.out.println(e.toString());
|
System.out.println(e.toString());
|
||||||
// java.lang.IllegalAccessError:
|
// java.lang.IllegalAccessError:
|
||||||
// tried to access method p2.c2.method2()V from class p1.c1 (p2.c2 is in module m2x of loader
|
// tried to access private 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>)
|
// 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 @") ||
|
if (!message.contains("class p1.c1 tried to access private 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 @")) {
|
!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());
|
throw new RuntimeException("Test Failed, an IAE was thrown with the wrong message: " + e.toString());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue