diff --git a/java_runtime/src/classes/java/lang/class_loader.rs b/java_runtime/src/classes/java/lang/class_loader.rs index d9e8c999..1ac583ca 100644 --- a/java_runtime/src/classes/java/lang/class_loader.rs +++ b/java_runtime/src/classes/java/lang/class_loader.rs @@ -186,9 +186,10 @@ impl ClassLoader { } let name_str = JavaLangString::to_rust_string(jvm, &name).await?; + let internal_name = name_str.replace('.', "/"); - if let Some(element_type_name) = name_str.strip_prefix('[') { - let ultimate_element_type = element_type_name.trim_start_matches('['); + if let Some(element_type_name) = internal_name.strip_prefix('[') { + let ultimate_element_type = name_str.trim_start_matches('['); let defining_loader = if let Some(element_class_name) = ultimate_element_type.strip_prefix('L').and_then(|name| name.strip_suffix(';')) { let element_class_name = JavaLangString::from_rust_string(jvm, element_class_name).await?; let element_class: ClassInstanceRef = jvm @@ -210,7 +211,7 @@ impl ClassLoader { jvm.invoke_virtual(&parent, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;", (name.clone(),)) .await? } else { - jvm.load_bootstrap_class(&name_str).await?.into() + jvm.load_bootstrap_class(&internal_name).await?.into() }; if !class.is_null() { @@ -243,12 +244,12 @@ impl ClassLoader { ) -> Result> { tracing::debug!("java.lang.ClassLoader::findLoadedClass({this:?}, {name:?})"); - let rust_name = JavaLangString::to_rust_string(jvm, &name).await?; - if !jvm.has_class(&rust_name) { + let internal_name = JavaLangString::to_rust_string(jvm, &name).await?.replace('.', "/"); + if !jvm.has_class(&internal_name) { return Ok(None.into()); } - let class = jvm.resolve_class(&rust_name).await?; + let class = jvm.resolve_class(&internal_name).await?; Ok(class.java_class().into()) } diff --git a/jvm/src/runtime/java_lang_class_loader.rs b/jvm/src/runtime/java_lang_class_loader.rs index c10907fb..f9a53202 100644 --- a/jvm/src/runtime/java_lang_class_loader.rs +++ b/jvm/src/runtime/java_lang_class_loader.rs @@ -17,7 +17,8 @@ impl JavaLangClassLoader { #[allow(clippy::borrowed_box)] pub async fn load_class(jvm: &Jvm, this: &Box, class_name: &str) -> Result>> { - let java_class_name = JavaLangString::from_rust_string(jvm, class_name).await?; + let binary_name = class_name.replace('/', "."); + let java_class_name = JavaLangString::from_rust_string(jvm, &binary_name).await?; let java_class: Option> = jvm .invoke_virtual(this, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;", (java_class_name,)) diff --git a/test_data/ClassMetadata$ByteLoader.class b/test_data/ClassMetadata$ByteLoader.class index 3677d58d..271de313 100644 Binary files a/test_data/ClassMetadata$ByteLoader.class and b/test_data/ClassMetadata$ByteLoader.class differ diff --git a/test_data/ClassMetadata$First.class b/test_data/ClassMetadata$First.class index b98fe838..5bb6faed 100644 Binary files a/test_data/ClassMetadata$First.class and b/test_data/ClassMetadata$First.class differ diff --git a/test_data/ClassMetadata$Payload.class b/test_data/ClassMetadata$Payload.class index ca68eb7e..cc0b9a99 100644 Binary files a/test_data/ClassMetadata$Payload.class and b/test_data/ClassMetadata$Payload.class differ diff --git a/test_data/ClassMetadata$Sample.class b/test_data/ClassMetadata$Sample.class index 6e4a02ab..185fae40 100644 Binary files a/test_data/ClassMetadata$Sample.class and b/test_data/ClassMetadata$Sample.class differ diff --git a/test_data/ClassMetadata$Second.class b/test_data/ClassMetadata$Second.class index a92d9143..122785e1 100644 Binary files a/test_data/ClassMetadata$Second.class and b/test_data/ClassMetadata$Second.class differ diff --git a/test_data/ClassMetadata.class b/test_data/ClassMetadata.class index fd7882ff..65b42555 100644 Binary files a/test_data/ClassMetadata.class and b/test_data/ClassMetadata.class differ diff --git a/test_data/ClassMetadata.txt b/test_data/ClassMetadata.txt index 058d99f0..b5e3255a 100644 --- a/test_data/ClassMetadata.txt +++ b/test_data/ClassMetadata.txt @@ -23,3 +23,7 @@ true true true true +true +true +true +true diff --git a/test_data/loader/Base.class b/test_data/loader/Base.class new file mode 100644 index 00000000..0eb08e7e Binary files /dev/null and b/test_data/loader/Base.class differ diff --git a/test_data/loader/Payload.class b/test_data/loader/Payload.class new file mode 100644 index 00000000..75c33771 Binary files /dev/null and b/test_data/loader/Payload.class differ diff --git a/test_data/src/ClassMetadata.java b/test_data/src/ClassMetadata.java index 16719b37..c1ecba4a 100644 --- a/test_data/src/ClassMetadata.java +++ b/test_data/src/ClassMetadata.java @@ -12,12 +12,14 @@ static class Payload { } static class ByteLoader extends ClassLoader { + int findCount; + ByteLoader(ClassLoader parent) { super(parent); } public Class loadClass(String name) throws ClassNotFoundException { - if (!name.equals("ClassMetadata$Payload")) { + if (!name.equals("ClassMetadata$Payload") && !name.startsWith("loader.")) { return super.loadClass(name); } @@ -27,7 +29,16 @@ public Class loadClass(String name) throws ClassNotFoundException { protected Class findClass(String name) throws ClassNotFoundException { try { - java.io.InputStream input = ClassMetadata.class.getResourceAsStream("ClassMetadata$Payload.class"); + findCount++; + String resourceName; + if (name.equals("ClassMetadata$Payload")) { + resourceName = "ClassMetadata$Payload.class"; + } else if (name.equals("loader.Payload")) { + resourceName = "loader/Payload.class"; + } else { + resourceName = "loader/Base.class"; + } + java.io.InputStream input = ClassMetadata.class.getResourceAsStream(resourceName); byte[] bytes = new byte[input.available()]; int offset = 0; while (offset < bytes.length) { @@ -84,5 +95,14 @@ public static void main(String[] args) throws Exception { System.out.println(payloadMatrix.getClassLoader() == customLoader); System.out.println(payloadArray.getComponentType() == payload); System.out.println(payloadMatrix.getComponentType() == payloadArray); + + Class packagedPayload = customLoader.loadClass("loader.Payload"); + Class packagedPayloadAgain = customLoader.loadClass("loader.Payload"); + Class packagedPayloadArray = customLoader.loadClass("[Lloader.Payload;"); + Class packagedPayloadArrayAgain = customLoader.loadClass("[Lloader.Payload;"); + System.out.println(packagedPayload == packagedPayloadAgain); + System.out.println(packagedPayloadArray == packagedPayloadArrayAgain); + System.out.println(packagedPayload.getSuperclass().getClassLoader() == customLoader); + System.out.println(customLoader.findCount == 3); } } diff --git a/test_data/src/loader/Base.java b/test_data/src/loader/Base.java new file mode 100644 index 00000000..54908d18 --- /dev/null +++ b/test_data/src/loader/Base.java @@ -0,0 +1,4 @@ +package loader; + +public class Base { +} diff --git a/test_data/src/loader/Payload.java b/test_data/src/loader/Payload.java new file mode 100644 index 00000000..e7bcddbe --- /dev/null +++ b/test_data/src/loader/Payload.java @@ -0,0 +1,4 @@ +package loader; + +public class Payload extends Base { +}