Skip to content

Commit facab57

Browse files
committed
Add logging, error pretty print on rustjava
1 parent 779706a commit facab57

File tree

5 files changed

+221
-12
lines changed

5 files changed

+221
-12
lines changed

Cargo.lock

Lines changed: 166 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ name = "rust_java"
4141
async-trait = { workspace = true }
4242
bytemuck = { workspace = true }
4343

44+
anyhow = { workspace = true }
4445
clap = { version = "^4.5", features = ["derive"] }
46+
tracing-subscriber = { version = "^0.3", features = ["env-filter"] }
4547

4648
jvm = { workspace = true }
4749
jvm_rust = { workspace = true }

src/lib.rs

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ mod runtime;
55
use std::{io::Write, path::Path};
66

77
use java_runtime::{RT_RUSTJAR, Runtime, get_bootstrap_class_loader};
8-
use jvm::{JavaValue, Jvm, Result, runtime::JavaLangString};
8+
use jvm::{JavaError, JavaValue, Jvm, Result, runtime::JavaLangString};
99

1010
use runtime::RuntimeImpl;
1111

@@ -14,10 +14,43 @@ pub enum StartType<'a> {
1414
Class(&'a Path),
1515
}
1616

17-
pub async fn run<T, S>(stdout: T, start_type: StartType<'_>, args: &[S], class_path: &[&Path]) -> Result<()>
17+
pub async fn run<T, S>(stdout: T, start_type: StartType<'_>, args: &[S], class_path: &[&Path]) -> anyhow::Result<()>
1818
where
1919
T: Sync + Send + Write + 'static,
2020
S: AsRef<str>,
21+
{
22+
let jvm = create_jvm(stdout, &start_type, class_path).await?;
23+
24+
let result = invoke_entrypoint(&jvm, &start_type, args).await;
25+
26+
if let Err(x) = result {
27+
Err(match x {
28+
JavaError::JavaException(x) => {
29+
let string_writer = jvm.new_class("java/io/StringWriter", "()V", ()).await.unwrap();
30+
let print_writer = jvm
31+
.new_class("java/io/PrintWriter", "(Ljava/io/Writer;)V", (string_writer.clone(),))
32+
.await
33+
.unwrap();
34+
35+
let _: () = jvm
36+
.invoke_virtual(&x, "printStackTrace", "(Ljava/io/PrintWriter;)V", (print_writer,))
37+
.await
38+
.unwrap();
39+
40+
let trace = jvm.invoke_virtual(&string_writer, "toString", "()Ljava/lang/String;", []).await.unwrap();
41+
42+
anyhow::anyhow!("Java Exception:\n{}", JavaLangString::to_rust_string(&jvm, &trace).await.unwrap())
43+
}
44+
JavaError::FatalError(x) => anyhow::anyhow!("Fatal error: {x}"),
45+
})
46+
} else {
47+
Ok(result?)
48+
}
49+
}
50+
51+
async fn create_jvm<T>(stdout: T, start_type: &StartType<'_>, class_path: &[&Path]) -> Result<Jvm>
52+
where
53+
T: Sync + Send + Write + 'static,
2154
{
2255
let runtime = Box::new(RuntimeImpl::new(stdout)) as Box<dyn Runtime>;
2356

@@ -33,16 +66,21 @@ where
3366
let class_path_str = format!("{RT_RUSTJAR}:{class_path_str}");
3467
let properties = [("java.class.path", class_path_str.as_str())].into_iter().collect();
3568

36-
let jvm = Jvm::new(bootstrap_class_loader, move || runtime.current_task_id(), properties).await?;
69+
Jvm::new(bootstrap_class_loader, move || runtime.current_task_id(), properties).await
70+
}
3771

72+
async fn invoke_entrypoint<S>(jvm: &Jvm, start_type: &StartType<'_>, args: &[S]) -> Result<()>
73+
where
74+
S: AsRef<str>,
75+
{
3876
let main_class_name = match start_type {
39-
StartType::Jar(x) => &get_jar_main_class(&jvm, x).await?,
77+
StartType::Jar(x) => &get_jar_main_class(jvm, x).await?,
4078
StartType::Class(x) => x.file_stem().unwrap().to_str().unwrap(),
4179
};
4280

4381
let mut java_args = Vec::with_capacity(args.len());
4482
for arg in args {
45-
java_args.push(JavaLangString::from_rust_string(&jvm, arg.as_ref()).await?);
83+
java_args.push(JavaLangString::from_rust_string(jvm, arg.as_ref()).await?);
4684
}
4785
let mut array = jvm.instantiate_array("Ljava/lang/String;", args.len()).await?;
4886
jvm.store_array(&mut array, 0, java_args).await.unwrap();

src/main.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
use std::{
2-
io,
2+
io::{self, stderr},
33
path::{Path, PathBuf},
44
};
55

66
use clap::{ArgGroup, Parser};
77

8-
use jvm::Result;
98
use rust_java::{StartType, run};
109

1110
#[derive(Parser)]
@@ -19,7 +18,12 @@ struct Opts {
1918
args: Vec<String>,
2019
}
2120

22-
pub fn main() -> Result<()> {
21+
pub fn main() -> anyhow::Result<()> {
22+
tracing_subscriber::fmt()
23+
.with_writer(stderr)
24+
.with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
25+
.init();
26+
2327
#[cfg(not(target_arch = "wasm32"))]
2428
let runtime = tokio::runtime::Runtime::new().unwrap();
2529
#[cfg(target_arch = "wasm32")]
@@ -28,7 +32,7 @@ pub fn main() -> Result<()> {
2832
runtime.block_on(async_main())
2933
}
3034

31-
pub async fn async_main() -> Result<()> {
35+
pub async fn async_main() -> anyhow::Result<()> {
3236
let opts = Opts::parse();
3337

3438
let start_type = if opts.main_class.is_some() {

tests/test_helper/mod.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use std::{
77
sync::{Arc, Mutex},
88
};
99

10-
use jvm::Result;
1110
use rust_java::{StartType, run};
1211

1312
struct Output {
@@ -24,7 +23,7 @@ impl io::Write for Output {
2423
}
2524
}
2625

27-
pub async fn run_class(path: &Path, class_path: &[&Path], args: &[String]) -> Result<String> {
26+
pub async fn run_class(path: &Path, class_path: &[&Path], args: &[String]) -> anyhow::Result<String> {
2827
let output = Arc::new(Mutex::new(Vec::new()));
2928

3029
run(Output { output: output.clone() }, StartType::Class(path), args, class_path).await?;
@@ -34,7 +33,7 @@ pub async fn run_class(path: &Path, class_path: &[&Path], args: &[String]) -> Re
3433
Ok(result)
3534
}
3635

37-
pub async fn run_jar(jar_path: &Path, args: &[String]) -> Result<String> {
36+
pub async fn run_jar(jar_path: &Path, args: &[String]) -> anyhow::Result<String> {
3837
let output = Arc::new(Mutex::new(Vec::new()));
3938

4039
run(Output { output: output.clone() }, StartType::Jar(jar_path), args, &[]).await?;

0 commit comments

Comments
 (0)