Skip to content

Commit

Permalink
8314819: [JVMCI] HotSpotJVMCIRuntime.lookupType throws unexpected Cla…
Browse files Browse the repository at this point in the history
…ssNotFoundException

Reviewed-by: never, thartmann
  • Loading branch information
Doug Simon committed Aug 24, 2023
1 parent c418933 commit 75e19e0
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 28 deletions.
5 changes: 1 addition & 4 deletions src/hotspot/share/jvmci/jvmciCompilerToVM.cpp
Expand Up @@ -617,10 +617,7 @@ C2V_VMENTRY_NULL(jobject, lookupType, (JNIEnv* env, jobject, jstring jname, ARGU
}

if (resolve) {
resolved_klass = SystemDictionary::resolve_or_null(class_name, class_loader, protection_domain, CHECK_NULL);
if (resolved_klass == nullptr) {
JVMCI_THROW_MSG_NULL(NoClassDefFoundError, str);
}
resolved_klass = SystemDictionary::resolve_or_fail(class_name, class_loader, protection_domain, true, CHECK_NULL);
} else {
if (Signature::has_envelope(class_name)) {
// This is a name from a signature. Strip off the trimmings.
Expand Down
Expand Up @@ -243,7 +243,7 @@ boolean methodIsIgnoredBySecurityStackWalk(HotSpotResolvedJavaMethodImpl method)
* @param accessingClass the class loader of this class is used for resolution. Must not be null.
* @param resolve force resolution to a {@link ResolvedJavaType}. If true, this method will
* either return a {@link ResolvedJavaType} or throw an exception
* @return the type for {@code name} or 0 if resolution failed and {@code resolve == false}
* @return the type for {@code name} or {@code null} if resolution failed and {@code resolve == false}
* @throws NoClassDefFoundError if {@code resolve == true} and the resolution failed
*/
HotSpotResolvedJavaType lookupType(String name, HotSpotResolvedObjectTypeImpl accessingClass, boolean resolve) throws NoClassDefFoundError {
Expand Down
Expand Up @@ -84,7 +84,7 @@ public static boolean methodIsIgnoredBySecurityStackWalk(HotSpotResolvedJavaMeth
}

public static HotSpotResolvedObjectType lookupType(String name,
Class<?> accessClass, boolean resolve) throws ClassNotFoundException {
Class<?> accessClass, boolean resolve) throws NoClassDefFoundError {
if (accessClass == null) {
throw new NullPointerException();
}
Expand All @@ -94,11 +94,7 @@ public static HotSpotResolvedObjectType lookupType(String name,

public static HotSpotResolvedObjectType lookupTypeHelper(String name,
Class<?> accessingClass, boolean resolve) {
try {
return lookupType(name, accessingClass, resolve);
} catch (ClassNotFoundException e) {
throw (NoClassDefFoundError) new NoClassDefFoundError().initCause(e);
}
return lookupType(name, accessingClass, resolve);
}

public static Object lookupConstantInPool(ConstantPool constantPool, int cpi, boolean resolve) {
Expand Down
70 changes: 53 additions & 17 deletions test/hotspot/jtreg/compiler/jvmci/compilerToVM/LookupTypeTest.java
Expand Up @@ -29,6 +29,8 @@
* @library ../common/patches
* @modules java.base/jdk.internal.access
* @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot
* jdk.internal.vm.ci/jdk.vm.ci.runtime
* jdk.internal.vm.ci/jdk.vm.ci.meta
* @build jdk.internal.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
* @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
* -XX:-UseJVMCICompiler
Expand All @@ -43,35 +45,64 @@
import jdk.test.lib.Asserts;
import jdk.test.lib.Utils;
import jdk.vm.ci.hotspot.CompilerToVMHelper;
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaType;

import java.util.HashSet;
import java.util.Set;
import java.io.ByteArrayOutputStream;
import java.io.CharArrayWriter;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;

public class LookupTypeTest {

/**
* Abstracts which lookup method is being tested.
*/
public interface Lookup {
ResolvedJavaType lookupType(String name, Class<?> accessingClass, boolean resolve);
}

public static void main(String args[]) {
LookupTypeTest test = new LookupTypeTest();
for (TestCase tcase : createTestCases()) {
test.runTest(tcase);

// Test CompilerToVM.lookupType
for (TestCase tcase : createTestCases(false, true)) {
test.runTest(tcase, CompilerToVMHelper::lookupType);
}

// Test HotSpotJVMCIRuntime.lookupType
HotSpotJVMCIRuntime runtime = HotSpotJVMCIRuntime.runtime();
MetaAccessProvider metaAccess = runtime.getHostJVMCIBackend().getMetaAccess();
for (TestCase tcase : createTestCases(true, false)) {
test.runTest(tcase, (name, accessingClass, resolve) -> (ResolvedJavaType) runtime.lookupType(name,
(HotSpotResolvedObjectType) metaAccess.lookupJavaType(accessingClass), resolve));
}
}

private static Set<TestCase> createTestCases() {
Set<TestCase> result = new HashSet<>();
private static List<TestCase> createTestCases(boolean allowPrimitive, boolean allowNullAccessingClass) {
List<TestCase> result = new ArrayList<>();
// a primitive class
result.add(new TestCase(Utils.toJVMTypeSignature(int.class),
if (allowPrimitive) {
result.add(new TestCase(Utils.toJVMTypeSignature(int.class),
LookupTypeTest.class, true, true));
} else {
result.add(new TestCase(Utils.toJVMTypeSignature(int.class),
LookupTypeTest.class, true, false, InternalError.class));
}
// lookup not existing class
result.add(new TestCase("Lsome_not_existing;", LookupTypeTest.class,
true, false, ClassNotFoundException.class));
true, false, NoClassDefFoundError.class));
// lookup invalid classname
result.add(new TestCase("L!@#$%^&**()[]{}?;", LookupTypeTest.class,
true, false, ClassNotFoundException.class));
true, false, NoClassDefFoundError.class));
// lookup package private class
result.add(new TestCase(
"Lcompiler/jvmci/compilerToVM/testcases/PackagePrivateClass;",
LookupTypeTest.class, true, false,
ClassNotFoundException.class));
NoClassDefFoundError.class));
// lookup usual class with resolve=true
result.add(new TestCase(Utils.toJVMTypeSignature(SingleSubclass.class),
LookupTypeTest.class, true, true));
Expand All @@ -80,25 +111,30 @@ private static Set<TestCase> createTestCases() {
Utils.toJVMTypeSignature(DoNotExtendClass.class),
LookupTypeTest.class, false, true));
// lookup usual class with null accessor
result.add(new TestCase(
if (allowNullAccessingClass) {
result.add(new TestCase(
Utils.toJVMTypeSignature(MultiSubclassedClass.class), null,
false, false, NullPointerException.class));
}
return result;
}

private void runTest(TestCase tcase) {
private void runTest(TestCase tcase, Lookup lookup) {
System.out.println(tcase);
HotSpotResolvedObjectType metaspaceKlass;
ResolvedJavaType metaspaceKlass;
try {
metaspaceKlass = CompilerToVMHelper.lookupType(tcase.className,
metaspaceKlass = lookup.lookupType(tcase.className,
tcase.accessing, tcase.resolve);
} catch (Throwable t) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
t.printStackTrace(new PrintStream(bos));
String tString = bos.toString();
Asserts.assertNotNull(tcase.expectedException,
"Assumed no exception, but got " + t);
"Assumed no exception, but got " + tString);
Asserts.assertFalse(tcase.isPositive,
"Got unexpected exception " + t);
"Got unexpected exception " + tString);
Asserts.assertEQ(t.getClass(), tcase.expectedException,
"Unexpected exception");
"Unexpected exception: " + tString);
// passed
return;
}
Expand Down
Expand Up @@ -183,4 +183,9 @@ public void jniEnomemTest() throws Exception {
output.shouldNotHaveExitValue(0);
}
}

@Test
public void lookupTypeTest() throws Exception {
// This is tested by compiler/jvmci/compilerToVM/LookupTypeTest.java
}
}

1 comment on commit 75e19e0

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.