@@ -5,7 +5,7 @@ mod runtime;
55use std:: { io:: Write , path:: Path } ;
66
77use 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
1010use 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 < ( ) >
1818where
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 ( ) ;
0 commit comments