8030221: Checking for anonymous class should check for NULL as well as potential nesting
Store the first non-anonymous class as the host when defining the anonymous class so don't need look for it later. Reviewed-by: dholmes, lfoltan
This commit is contained in:
parent
e3c3a54f7a
commit
2a74c06b8d
@ -861,6 +861,13 @@ Unsafe_DefineAnonymousClass_impl(JNIEnv *env,
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Klass* host_klass = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(host_class));
|
const Klass* host_klass = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(host_class));
|
||||||
|
|
||||||
|
// Make sure it's the real host class, not another anonymous class.
|
||||||
|
while (host_klass != NULL && host_klass->is_instance_klass() &&
|
||||||
|
InstanceKlass::cast(host_klass)->is_anonymous()) {
|
||||||
|
host_klass = InstanceKlass::cast(host_klass)->host_klass();
|
||||||
|
}
|
||||||
|
|
||||||
// Primitive types have NULL Klass* fields in their java.lang.Class instances.
|
// Primitive types have NULL Klass* fields in their java.lang.Class instances.
|
||||||
if (host_klass == NULL) {
|
if (host_klass == NULL) {
|
||||||
THROW_0(vmSymbols::java_lang_IllegalArgumentException());
|
THROW_0(vmSymbols::java_lang_IllegalArgumentException());
|
||||||
|
@ -660,11 +660,13 @@ bool Reflection::verify_field_access(const Klass* current_class,
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Klass* host_class = current_class;
|
const Klass* host_class = current_class;
|
||||||
while (host_class->is_instance_klass() &&
|
if (host_class->is_instance_klass() &&
|
||||||
InstanceKlass::cast(host_class)->is_anonymous()) {
|
InstanceKlass::cast(host_class)->is_anonymous()) {
|
||||||
const Klass* next_host_class = InstanceKlass::cast(host_class)->host_klass();
|
host_class = InstanceKlass::cast(host_class)->host_klass();
|
||||||
if (next_host_class == NULL) break;
|
assert(host_class != NULL, "Anonymous class has null host class");
|
||||||
host_class = next_host_class;
|
assert(!(host_class->is_instance_klass() &&
|
||||||
|
InstanceKlass::cast(host_class)->is_anonymous()),
|
||||||
|
"host_class should not be anonymous");
|
||||||
}
|
}
|
||||||
if (host_class == field_class) {
|
if (host_class == field_class) {
|
||||||
return true;
|
return true;
|
||||||
|
90
hotspot/test/runtime/Unsafe/NestedUnsafe.java
Normal file
90
hotspot/test/runtime/Unsafe/NestedUnsafe.java
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @summary Creates an anonymous class inside of an anonymous class.
|
||||||
|
* @library /testlibrary
|
||||||
|
* @modules java.base/jdk.internal.misc
|
||||||
|
* java.compiler
|
||||||
|
* java.management
|
||||||
|
* @run main NestedUnsafe
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.security.ProtectionDomain;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.lang.*;
|
||||||
|
import jdk.test.lib.*;
|
||||||
|
import jdk.internal.misc.Unsafe;
|
||||||
|
import static jdk.test.lib.Asserts.*;
|
||||||
|
|
||||||
|
// package p;
|
||||||
|
|
||||||
|
public class NestedUnsafe {
|
||||||
|
// The String concatenation should create the nested anonymous class.
|
||||||
|
static byte klassbuf[] = InMemoryJavaCompiler.compile("TestClass",
|
||||||
|
"public class TestClass { " +
|
||||||
|
" public static void concat(String one, String two) throws Throwable { " +
|
||||||
|
" System.out.println(one + two);" +
|
||||||
|
" } } ");
|
||||||
|
|
||||||
|
public static void main(String args[]) throws Exception {
|
||||||
|
Unsafe unsafe = Utils.getUnsafe();
|
||||||
|
|
||||||
|
Class klass = unsafe.defineAnonymousClass(NestedUnsafe.class, klassbuf, new Object[0]);
|
||||||
|
unsafe.ensureClassInitialized(klass);
|
||||||
|
Class[] cArgs = new Class[2];
|
||||||
|
cArgs[0] = String.class;
|
||||||
|
cArgs[1] = String.class;
|
||||||
|
try {
|
||||||
|
klass.getMethod("concat", cArgs).invoke(null, "AA", "BB");
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
throw new RuntimeException("Exception: " + ex.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// The anonymous class calls defineAnonymousClass creating a nested anonymous class.
|
||||||
|
byte klassbuf2[] = InMemoryJavaCompiler.compile("TestClass2",
|
||||||
|
"import jdk.internal.misc.Unsafe; " +
|
||||||
|
"public class TestClass2 { " +
|
||||||
|
" public static void doit() throws Throwable { " +
|
||||||
|
" Unsafe unsafe = jdk.internal.misc.Unsafe.getUnsafe(); " +
|
||||||
|
" Class klass2 = unsafe.defineAnonymousClass(TestClass2.class, NestedUnsafe.klassbuf, new Object[0]); " +
|
||||||
|
" unsafe.ensureClassInitialized(klass2); " +
|
||||||
|
" Class[] dArgs = new Class[2]; " +
|
||||||
|
" dArgs[0] = String.class; " +
|
||||||
|
" dArgs[1] = String.class; " +
|
||||||
|
" try { " +
|
||||||
|
" klass2.getMethod(\"concat\", dArgs).invoke(null, \"CC\", \"DD\"); " +
|
||||||
|
" } catch (Throwable ex) { " +
|
||||||
|
" throw new RuntimeException(\"Exception: \" + ex.toString()); " +
|
||||||
|
" } " +
|
||||||
|
"} } ",
|
||||||
|
"-XaddExports:java.base/jdk.internal.misc=ALL-UNNAMED");
|
||||||
|
Class klass2 = unsafe.defineAnonymousClass(NestedUnsafe.class, klassbuf2, new Object[0]);
|
||||||
|
try {
|
||||||
|
klass2.getMethod("doit").invoke(null);
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
throw new RuntimeException("Exception: " + ex.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user