Skip to content

Commit 02d60f3

Browse files
Merge pull request #533 from theseus-rs/correct-jvm-initialization
fix: correct JVM initialization process to call java.lang.ref.Reference.<clinit>()
2 parents a67ea99 + 5c81920 commit 02d60f3

File tree

3 files changed

+16
-72
lines changed

3 files changed

+16
-72
lines changed

ristretto_vm/src/intrinsic_methods/java/lang/system.rs

Lines changed: 4 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,8 @@ use crate::thread::Thread;
99
use async_recursion::async_recursion;
1010
use parking_lot::RwLock;
1111
use ristretto_classfile::VersionSpecification::{Any, LessThanOrEqual};
12-
use ristretto_classfile::attributes::{Attribute, Instruction};
13-
use ristretto_classfile::{
14-
ClassAccessFlags, ClassFile, ConstantPool, JAVA_8, JAVA_11, JAVA_17, MethodAccessFlags,
15-
};
16-
use ristretto_classloader::{Class, Object, Reference, Value};
12+
use ristretto_classfile::{JAVA_8, JAVA_11, JAVA_17};
13+
use ristretto_classloader::{Reference, Value};
1714
use ristretto_gc::Gc;
1815
use ristretto_macros::intrinsic_method;
1916
use std::env::consts::OS;
@@ -328,14 +325,14 @@ pub(crate) async fn register_natives(
328325
_parameters: Parameters,
329326
) -> Result<Option<Value>> {
330327
let vm = thread.vm()?;
328+
331329
if vm.java_major_version() <= JAVA_8.java() {
332330
thread
333331
.invoke("java.lang.System", "setJavaLangAccess()V", &[] as &[Value])
334332
.await?;
335-
return Ok(None);
336333
}
337334

338-
if vm.java_major_version() == JAVA_17.java() {
335+
if vm.java_major_version() <= JAVA_17.java() {
339336
// Force the initialization of the system properties; this is required because no security
340337
// manager is installed and when System::initPhase1() is called, the resulting call chain:
341338
//
@@ -357,74 +354,9 @@ pub(crate) async fn register_natives(
357354
.await?;
358355
}
359356

360-
let java_major_version = vm.java_major_version();
361-
let package_name = if java_major_version <= JAVA_8.java() {
362-
"sun/misc"
363-
} else if java_major_version <= JAVA_11.java() {
364-
"jdk/internal/misc"
365-
} else {
366-
"jdk/internal/access"
367-
};
368-
let java_lang_ref_access = java_lang_ref_access_class(&thread, package_name).await?;
369-
let java_lang_ref_access = Value::from(Object::new(java_lang_ref_access)?);
370-
let shared_secrets_class = format!("{package_name}/SharedSecrets");
371-
thread
372-
.invoke(
373-
&shared_secrets_class,
374-
format!("setJavaLangRefAccess(L{package_name}/JavaLangRefAccess;)V"),
375-
&[java_lang_ref_access],
376-
)
377-
.await?;
378-
379357
Ok(None)
380358
}
381359

382-
/// Create a class for `<package>.JavaLangRefAccess` to bootstrap the VM startup process.
383-
pub(crate) async fn java_lang_ref_access_class(
384-
thread: &Arc<Thread>,
385-
package_name: &str,
386-
) -> Result<Arc<Class>> {
387-
let vm = thread.vm()?;
388-
let java_class_file_version = vm.java_class_file_version();
389-
let mut constant_pool = ConstantPool::default();
390-
let this_class = constant_pool.add_class("ristretto/internal/access/JavaLangRefAccess")?;
391-
let interface_name = format!("{package_name}/JavaLangRefAccess");
392-
let interface_class = constant_pool.add_class(&interface_name)?;
393-
let code_index = constant_pool.add_utf8("Code")?;
394-
let start_threads_index = constant_pool.add_utf8("startThreads")?;
395-
let start_threads_descriptor_index = constant_pool.add_utf8("()V")?;
396-
397-
let start_threads_method_attributes = vec![Attribute::Code {
398-
name_index: code_index,
399-
max_stack: 0,
400-
max_locals: 1,
401-
code: vec![Instruction::Return],
402-
exception_table: Vec::new(),
403-
attributes: Vec::new(),
404-
}];
405-
let start_threads_method = ristretto_classfile::Method {
406-
access_flags: MethodAccessFlags::PUBLIC,
407-
name_index: start_threads_index,
408-
descriptor_index: start_threads_descriptor_index,
409-
attributes: start_threads_method_attributes,
410-
};
411-
let class_file = ClassFile {
412-
version: java_class_file_version.clone(),
413-
access_flags: ClassAccessFlags::PUBLIC,
414-
constant_pool,
415-
this_class,
416-
methods: vec![start_threads_method],
417-
interfaces: vec![interface_class],
418-
..Default::default()
419-
};
420-
421-
let java_lang_ref_access = Class::from(None, class_file)?;
422-
let interface = thread.class(&interface_name).await?;
423-
java_lang_ref_access.set_interfaces(vec![interface])?;
424-
thread.register_class(java_lang_ref_access.clone()).await?;
425-
Ok(java_lang_ref_access)
426-
}
427-
428360
#[intrinsic_method("java/lang/System.setIn0(Ljava/io/InputStream;)V", Any)]
429361
#[async_recursion(?Send)]
430362
pub(crate) async fn set_in_0(

ristretto_vm/src/intrinsic_methods/java/lang/thread.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,13 @@ pub(crate) async fn start_0(
379379
thread: Arc<Thread>,
380380
mut parameters: Parameters,
381381
) -> Result<Option<Value>> {
382+
if !matches!(
383+
std::env::var("RISTRETTO_THREADING"),
384+
Ok(v) if matches!(&*v.to_ascii_lowercase(), "1" | "true" | "yes" | "on")
385+
) {
386+
return Ok(None);
387+
}
388+
382389
let thread_object = parameters.pop()?;
383390
let (thread_class, thread_id) = {
384391
let mut thread_object = thread_object.as_object_mut()?;

ristretto_vm/src/vm.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,11 @@ impl VM {
289289
self.initialize_primordial_thread().await?;
290290
startup_trace!("[vm] primordial thread");
291291

292+
// Load the java.lang.ref.Reference class explicitly so that the class initializer calls
293+
// SharedSecrets.setJavaLangRefAccess(...) at the appropriate time in the JVM initialization
294+
// process.
295+
let _ = self.class("java.lang.ref.Reference").await?;
296+
292297
if self.java_class_file_version <= JAVA_8 {
293298
self.invoke(
294299
"java.lang.System",

0 commit comments

Comments
 (0)