Skip to content

Commit 9a4a05e

Browse files
committed
Store Throwable stack trace as Java String array instead of Rust pointer
1 parent 34ebc38 commit 9a4a05e

1 file changed

Lines changed: 20 additions & 11 deletions

File tree

java_runtime/src/classes/java/lang/throwable.rs

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
use alloc::{boxed::Box, format, string::String as RustString, sync::Arc, vec, vec::Vec};
1+
use alloc::{boxed::Box, format, vec, vec::Vec};
22

33
use java_class_proto::{JavaFieldProto, JavaMethodProto};
4-
use jvm::{ClassInstance, ClassInstanceRef, Jvm, Result, runtime::JavaLangString};
4+
use jvm::{Array, ClassInstance, ClassInstanceRef, Jvm, Result, runtime::JavaLangString};
55

66
use crate::{
77
RuntimeClassProto, RuntimeContext,
@@ -46,7 +46,7 @@ impl Throwable {
4646
],
4747
fields: vec![
4848
JavaFieldProto::new("detailMessage", "Ljava/lang/String;", Default::default()),
49-
JavaFieldProto::new("stackTrace", "[B", Default::default()),
49+
JavaFieldProto::new("stackTrace", "[Ljava/lang/String;", Default::default()),
5050
],
5151
access_flags: Default::default(),
5252
}
@@ -77,9 +77,13 @@ impl Throwable {
7777
async fn fill_in_stack_trace(jvm: &Jvm, _: &mut RuntimeContext, mut this: ClassInstanceRef<Self>) -> Result<ClassInstanceRef<Self>> {
7878
tracing::debug!("java.lang.Throwable::fillInStackTrace({:?})", &this);
7979

80-
let stack_trace = Arc::new(jvm.stack_trace());
81-
82-
jvm.put_rust_object_field(&mut this, "stackTrace", stack_trace).await?;
80+
let stack_trace = jvm.stack_trace();
81+
let mut stack_trace_array = jvm.instantiate_array("Ljava/lang/String;", stack_trace.len()).await?;
82+
for (i, line) in stack_trace.iter().enumerate() {
83+
let java_line = JavaLangString::from_rust_string(jvm, line).await?;
84+
jvm.store_array(&mut stack_trace_array, i, core::iter::once(java_line)).await?;
85+
}
86+
jvm.put_field(&mut this, "stackTrace", "[Ljava/lang/String;", stack_trace_array).await?;
8387

8488
Ok(this)
8589
}
@@ -146,18 +150,23 @@ impl Throwable {
146150
}
147151

148152
async fn do_print_stack_trace(jvm: &Jvm, this: ClassInstanceRef<Self>, stream_or_writer: Box<dyn ClassInstance>) -> Result<()> {
149-
let stack_trace: Arc<Vec<RustString>> = jvm.get_rust_object_field(&this, "stackTrace").await?;
153+
let stack_trace: ClassInstanceRef<Array<ClassInstanceRef<String>>> = jvm.get_field(&this, "stackTrace", "[Ljava/lang/String;").await?;
150154

151155
// TODO we can call println(Ljava/lang/Object;)V
152156
let string: ClassInstanceRef<String> = jvm.invoke_virtual(&this, "toString", "()Ljava/lang/String;", ()).await?;
153157
let _: () = jvm
154158
.invoke_virtual(&stream_or_writer, "println", "(Ljava/lang/String;)V", (string,))
155159
.await?;
156160

157-
for line in stack_trace.iter() {
158-
let line = format!("\tat {line}");
159-
let line = JavaLangString::from_rust_string(jvm, &line).await?;
160-
let _: () = jvm.invoke_virtual(&stream_or_writer, "println", "(Ljava/lang/String;)V", (line,)).await?;
161+
if !stack_trace.is_null() {
162+
let length = jvm.array_length(&stack_trace).await?;
163+
let lines: Vec<ClassInstanceRef<String>> = jvm.load_array(&stack_trace, 0, length).await?;
164+
for line_ref in lines {
165+
let line = JavaLangString::to_rust_string(jvm, &line_ref).await?;
166+
let line = format!("\tat {line}");
167+
let line = JavaLangString::from_rust_string(jvm, &line).await?;
168+
let _: () = jvm.invoke_virtual(&stream_or_writer, "println", "(Ljava/lang/String;)V", (line,)).await?;
169+
}
161170
}
162171

163172
Ok(())

0 commit comments

Comments
 (0)