├── java └── example │ ├── settings.gradle │ ├── build.gradle │ ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties │ ├── src │ └── main │ │ └── java │ │ └── jvmrust │ │ ├── ch07 │ │ ├── Vector.java │ │ ├── InvokeInterfaceTest.java │ │ ├── FibonacciTest.java │ │ ├── Vector3D.java │ │ ├── InvokeSpecialTest.java │ │ ├── Vector2D.java │ │ ├── InvokeVirtualTest.java │ │ ├── AccSuperDemo.java │ │ ├── InvokeDemo.java │ │ └── ClinitTest.java │ │ ├── ch01 │ │ └── HelloWorld.java │ │ ├── ch08 │ │ ├── PrintArgs.java │ │ ├── MultianewarrayDemo.java │ │ ├── StringTest.java │ │ ├── ArrayDemo.java │ │ └── Array3D.java │ │ ├── ch05 │ │ ├── GaussTest.java │ │ └── ShTest.java │ │ ├── ch09 │ │ ├── StringBuilderTest.java │ │ ├── ArrayListTest.java │ │ ├── ObjectTest.java │ │ ├── StringTest.java │ │ ├── HashMapTest.java │ │ └── PrintlnTest.java │ │ ├── ch06 │ │ ├── FieldTest.java │ │ ├── Circle.java │ │ ├── FieldResolutionTest.java │ │ └── MyObject.java │ │ ├── ch04 │ │ └── Math.java │ │ ├── ch10 │ │ ├── StackTraceTest.java │ │ ├── ExceptionTest2.java │ │ ├── ArgsTest.java │ │ └── ExceptionTest1.java │ │ └── ch03 │ │ └── ClassFileTest.java │ ├── .gitattributes │ └── .gitignore ├── src └── main.rs ├── ch04_rtda ├── src │ ├── rtda │ │ ├── object.rs │ │ ├── frame.rs │ │ └── thread.rs │ ├── rtda.rs │ ├── types.rs │ └── classfile │ │ ├── attribute_info │ │ ├── attr_constant_value.rs │ │ ├── attr_exceptions.rs │ │ ├── attr_signature.rs │ │ ├── attr_unparsed.rs │ │ ├── attr_source_file.rs │ │ ├── attr_markers.rs │ │ └── attr_enclosing_method.rs │ │ └── constant_pool │ │ ├── cp_name_and_type.rs │ │ ├── cp_string.rs │ │ └── cp_class.rs ├── Cargo.toml └── README.md ├── ch09_native ├── src │ ├── instructions │ │ ├── reserved │ │ │ └── mod.rs │ │ ├── stack │ │ │ ├── mod.rs │ │ │ └── swap.rs │ │ ├── extended │ │ │ ├── mod.rs │ │ │ └── goto_w.rs │ │ ├── conversions │ │ │ └── mod.rs │ │ ├── constants │ │ │ ├── mod.rs │ │ │ └── nop.rs │ │ ├── control │ │ │ ├── mod.rs │ │ │ └── goto.rs │ │ ├── loads │ │ │ └── mod.rs │ │ ├── comparisons │ │ │ ├── mod.rs │ │ │ ├── lcmp.rs │ │ │ ├── dcmp.rs │ │ │ └── fcmp.rs │ │ ├── stores │ │ │ └── mod.rs │ │ ├── base │ │ │ └── instruction.rs │ │ ├── math │ │ │ ├── mod.rs │ │ │ ├── iinc.rs │ │ │ ├── or.rs │ │ │ ├── xor.rs │ │ │ └── and.rs │ │ └── references │ │ │ ├── arraylength.rs │ │ │ └── mod.rs │ ├── types.rs │ ├── rtda.rs │ ├── rtda │ │ └── heap │ │ │ └── mod.rs │ ├── native │ │ └── java │ │ │ └── lang │ │ │ ├── String.rs │ │ │ ├── Object.rs │ │ │ ├── Float.rs │ │ │ └── Double.rs │ └── classfile │ │ ├── attribute_info │ │ ├── attr_exceptions.rs │ │ ├── attr_constant_value.rs │ │ ├── attr_source_file.rs │ │ ├── attr_unparsed.rs │ │ └── attr_signature.rs │ │ └── constant_pool │ │ ├── cp_name_and_type.rs │ │ ├── cp_class.rs │ │ └── cp_string.rs ├── Cargo.toml └── README.md ├── ch10_exception ├── src │ ├── instructions │ │ ├── reserved │ │ │ └── mod.rs │ │ ├── stack │ │ │ ├── mod.rs │ │ │ └── swap.rs │ │ ├── extended │ │ │ ├── mod.rs │ │ │ └── goto_w.rs │ │ ├── conversions │ │ │ └── mod.rs │ │ ├── constants │ │ │ ├── mod.rs │ │ │ └── nop.rs │ │ ├── control │ │ │ ├── mod.rs │ │ │ └── goto.rs │ │ ├── loads │ │ │ └── mod.rs │ │ ├── comparisons │ │ │ ├── mod.rs │ │ │ ├── lcmp.rs │ │ │ └── fcmp.rs │ │ ├── stores │ │ │ └── mod.rs │ │ ├── base │ │ │ └── instruction.rs │ │ ├── math │ │ │ ├── mod.rs │ │ │ ├── iinc.rs │ │ │ ├── or.rs │ │ │ ├── xor.rs │ │ │ └── and.rs │ │ └── references │ │ │ ├── arraylength.rs │ │ │ └── mod.rs │ ├── types.rs │ ├── rtda.rs │ ├── rtda │ │ └── heap │ │ │ └── mod.rs │ ├── native │ │ └── java │ │ │ └── lang │ │ │ ├── String.rs │ │ │ ├── Object.rs │ │ │ ├── Float.rs │ │ │ └── Double.rs │ └── classfile │ │ ├── attribute_info │ │ ├── attr_exceptions.rs │ │ ├── attr_constant_value.rs │ │ ├── attr_unparsed.rs │ │ └── attr_signature.rs │ │ └── constant_pool │ │ ├── cp_name_and_type.rs │ │ ├── cp_class.rs │ │ └── cp_string.rs ├── Cargo.toml └── README.md ├── ch05_instructions ├── src │ ├── rtda │ │ ├── object.rs │ │ └── thread.rs │ ├── instructions │ │ ├── stack │ │ │ ├── mod.rs │ │ │ ├── swap.rs │ │ │ └── pop.rs │ │ ├── constants │ │ │ ├── mod.rs │ │ │ ├── nop.rs │ │ │ └── ipush.rs │ │ ├── extended │ │ │ ├── mod.rs │ │ │ └── goto_w.rs │ │ ├── control │ │ │ ├── mod.rs │ │ │ └── goto.rs │ │ ├── conversions │ │ │ └── mod.rs │ │ ├── loads │ │ │ └── mod.rs │ │ ├── stores │ │ │ └── mod.rs │ │ ├── base │ │ │ ├── mod.rs │ │ │ └── instruction.rs │ │ ├── comparisons │ │ │ ├── mod.rs │ │ │ ├── lcmp.rs │ │ │ ├── fcmp.rs │ │ │ └── dcmp.rs │ │ └── math │ │ │ ├── mod.rs │ │ │ ├── iinc.rs │ │ │ ├── or.rs │ │ │ ├── xor.rs │ │ │ └── and.rs │ ├── rtda.rs │ ├── types.rs │ └── classfile │ │ ├── attribute_info │ │ ├── attr_constant_value.rs │ │ ├── attr_exceptions.rs │ │ ├── attr_source_file.rs │ │ ├── attr_unparsed.rs │ │ └── attr_signature.rs │ │ └── constant_pool │ │ ├── cp_name_and_type.rs │ │ ├── cp_string.rs │ │ └── cp_class.rs ├── Cargo.toml └── README.md ├── ch06_rtda_heap ├── src │ ├── instructions │ │ ├── stack │ │ │ ├── mod.rs │ │ │ ├── swap.rs │ │ │ └── pop.rs │ │ ├── extended │ │ │ ├── mod.rs │ │ │ └── goto_w.rs │ │ ├── control │ │ │ ├── mod.rs │ │ │ └── goto.rs │ │ ├── conversions │ │ │ └── mod.rs │ │ ├── constants │ │ │ ├── mod.rs │ │ │ ├── nop.rs │ │ │ └── ipush.rs │ │ ├── loads │ │ │ └── mod.rs │ │ ├── stores │ │ │ └── mod.rs │ │ ├── base │ │ │ ├── mod.rs │ │ │ └── instruction.rs │ │ ├── comparisons │ │ │ ├── mod.rs │ │ │ ├── lcmp.rs │ │ │ ├── dcmp.rs │ │ │ └── fcmp.rs │ │ ├── math │ │ │ ├── mod.rs │ │ │ ├── iinc.rs │ │ │ ├── or.rs │ │ │ ├── xor.rs │ │ │ └── and.rs │ │ └── references │ │ │ ├── mod.rs │ │ │ └── invokespecial.rs │ ├── rtda │ │ ├── heap │ │ │ └── mod.rs │ │ └── thread.rs │ ├── types.rs │ ├── rtda.rs │ └── classfile │ │ ├── attribute_info │ │ ├── attr_exceptions.rs │ │ ├── attr_constant_value.rs │ │ ├── attr_source_file.rs │ │ ├── attr_unparsed.rs │ │ └── attr_signature.rs │ │ └── constant_pool │ │ └── cp_name_and_type.rs └── Cargo.toml ├── ch07_method_invoke ├── src │ ├── instructions │ │ ├── stack │ │ │ ├── mod.rs │ │ │ ├── swap.rs │ │ │ └── pop.rs │ │ ├── extended │ │ │ ├── mod.rs │ │ │ └── goto_w.rs │ │ ├── conversions │ │ │ └── mod.rs │ │ ├── constants │ │ │ ├── mod.rs │ │ │ ├── nop.rs │ │ │ └── ipush.rs │ │ ├── loads │ │ │ └── mod.rs │ │ ├── stores │ │ │ └── mod.rs │ │ ├── control │ │ │ ├── mod.rs │ │ │ └── goto.rs │ │ ├── comparisons │ │ │ ├── mod.rs │ │ │ ├── lcmp.rs │ │ │ ├── dcmp.rs │ │ │ └── fcmp.rs │ │ ├── base │ │ │ └── instruction.rs │ │ ├── math │ │ │ ├── mod.rs │ │ │ ├── iinc.rs │ │ │ ├── or.rs │ │ │ ├── xor.rs │ │ │ └── and.rs │ │ └── references │ │ │ └── mod.rs │ ├── types.rs │ ├── rtda.rs │ ├── rtda │ │ └── heap │ │ │ └── mod.rs │ └── classfile │ │ ├── attribute_info │ │ ├── attr_exceptions.rs │ │ ├── attr_constant_value.rs │ │ ├── attr_unparsed.rs │ │ ├── attr_source_file.rs │ │ └── attr_signature.rs │ │ └── constant_pool │ │ ├── cp_name_and_type.rs │ │ ├── cp_class.rs │ │ └── cp_string.rs ├── Cargo.toml └── README.md ├── ch08_array_string ├── src │ ├── instructions │ │ ├── stack │ │ │ ├── mod.rs │ │ │ └── swap.rs │ │ ├── extended │ │ │ ├── mod.rs │ │ │ └── goto_w.rs │ │ ├── conversions │ │ │ └── mod.rs │ │ ├── constants │ │ │ ├── mod.rs │ │ │ └── nop.rs │ │ ├── control │ │ │ ├── mod.rs │ │ │ └── goto.rs │ │ ├── loads │ │ │ └── mod.rs │ │ ├── comparisons │ │ │ ├── mod.rs │ │ │ ├── lcmp.rs │ │ │ └── dcmp.rs │ │ ├── stores │ │ │ └── mod.rs │ │ ├── base │ │ │ └── instruction.rs │ │ ├── math │ │ │ ├── mod.rs │ │ │ ├── iinc.rs │ │ │ ├── or.rs │ │ │ ├── xor.rs │ │ │ └── and.rs │ │ └── references │ │ │ ├── arraylength.rs │ │ │ └── mod.rs │ ├── types.rs │ ├── rtda.rs │ ├── rtda │ │ └── heap │ │ │ └── mod.rs │ └── classfile │ │ ├── attribute_info │ │ ├── attr_exceptions.rs │ │ ├── attr_constant_value.rs │ │ ├── attr_source_file.rs │ │ ├── attr_unparsed.rs │ │ └── attr_signature.rs │ │ └── constant_pool │ │ ├── cp_name_and_type.rs │ │ ├── cp_class.rs │ │ └── cp_string.rs ├── Cargo.toml └── README.md ├── ch01_cmd ├── Cargo.toml ├── README.md └── src │ └── main.rs ├── .cargo └── config.toml ├── ch03_classfile ├── src │ ├── types.rs │ └── classfile │ │ ├── attribute_info │ │ ├── attr_constant_value.rs │ │ ├── attr_exceptions.rs │ │ ├── attr_signature.rs │ │ ├── attr_unparsed.rs │ │ ├── attr_source_file.rs │ │ ├── attr_markers.rs │ │ └── attr_enclosing_method.rs │ │ └── constant_pool │ │ ├── cp_name_and_type.rs │ │ ├── cp_string.rs │ │ └── cp_class.rs └── Cargo.toml ├── ch02_classpath ├── Cargo.toml ├── README.md └── src │ └── main.rs ├── .gitignore ├── Cargo.toml └── README.md /java/example/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'example' 2 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | println!("Hello, jvm rust!"); 3 | } 4 | -------------------------------------------------------------------------------- /ch04_rtda/src/rtda/object.rs: -------------------------------------------------------------------------------- 1 | #[derive(Clone, Debug)] 2 | pub struct Object { 3 | // TODO 4 | } 5 | -------------------------------------------------------------------------------- /ch09_native/src/instructions/reserved/mod.rs: -------------------------------------------------------------------------------- 1 | mod invokenative; 2 | 3 | pub use self::invokenative::*; 4 | -------------------------------------------------------------------------------- /ch10_exception/src/instructions/reserved/mod.rs: -------------------------------------------------------------------------------- 1 | mod invokenative; 2 | 3 | pub use self::invokenative::*; 4 | -------------------------------------------------------------------------------- /java/example/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "java" 3 | } 4 | 5 | repositories { 6 | mavenCentral() 7 | } 8 | -------------------------------------------------------------------------------- /ch05_instructions/src/rtda/object.rs: -------------------------------------------------------------------------------- 1 | #[derive(Clone, Debug, PartialEq)] 2 | pub struct Object { 3 | // TODO 4 | } 5 | -------------------------------------------------------------------------------- /java/example/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dxx/jvm-rust/HEAD/java/example/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /ch06_rtda_heap/src/instructions/stack/mod.rs: -------------------------------------------------------------------------------- 1 | mod pop; 2 | mod dup; 3 | mod swap; 4 | 5 | pub use self::pop::*; 6 | pub use self::dup::*; 7 | pub use self::swap::*; 8 | -------------------------------------------------------------------------------- /ch09_native/src/instructions/stack/mod.rs: -------------------------------------------------------------------------------- 1 | mod pop; 2 | mod dup; 3 | mod swap; 4 | 5 | pub use self::pop::*; 6 | pub use self::dup::*; 7 | pub use self::swap::*; 8 | -------------------------------------------------------------------------------- /ch10_exception/src/instructions/stack/mod.rs: -------------------------------------------------------------------------------- 1 | mod pop; 2 | mod dup; 3 | mod swap; 4 | 5 | pub use self::pop::*; 6 | pub use self::dup::*; 7 | pub use self::swap::*; 8 | -------------------------------------------------------------------------------- /java/example/src/main/java/jvmrust/ch07/Vector.java: -------------------------------------------------------------------------------- 1 | package jvmrust.ch07; 2 | 3 | public interface Vector { 4 | 5 | public void multiply(double s); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /ch05_instructions/src/instructions/stack/mod.rs: -------------------------------------------------------------------------------- 1 | mod pop; 2 | mod dup; 3 | mod swap; 4 | 5 | pub use self::pop::*; 6 | pub use self::dup::*; 7 | pub use self::swap::*; 8 | -------------------------------------------------------------------------------- /ch07_method_invoke/src/instructions/stack/mod.rs: -------------------------------------------------------------------------------- 1 | mod pop; 2 | mod dup; 3 | mod swap; 4 | 5 | pub use self::pop::*; 6 | pub use self::dup::*; 7 | pub use self::swap::*; 8 | -------------------------------------------------------------------------------- /ch08_array_string/src/instructions/stack/mod.rs: -------------------------------------------------------------------------------- 1 | mod pop; 2 | mod dup; 3 | mod swap; 4 | 5 | pub use self::pop::*; 6 | pub use self::dup::*; 7 | pub use self::swap::*; 8 | -------------------------------------------------------------------------------- /ch05_instructions/src/instructions/constants/mod.rs: -------------------------------------------------------------------------------- 1 | mod nop; 2 | mod consts; 3 | mod ipush; 4 | 5 | pub use self::nop::*; 6 | pub use self::consts::*; 7 | pub use self::ipush::*; 8 | -------------------------------------------------------------------------------- /ch06_rtda_heap/src/instructions/extended/mod.rs: -------------------------------------------------------------------------------- 1 | mod goto_w; 2 | mod ifnull; 3 | mod wide; 4 | 5 | pub use self::goto_w::*; 6 | pub use self::ifnull::*; 7 | pub use self::wide::*; 8 | -------------------------------------------------------------------------------- /ch09_native/src/instructions/extended/mod.rs: -------------------------------------------------------------------------------- 1 | mod goto_w; 2 | mod ifnull; 3 | mod wide; 4 | 5 | pub use self::goto_w::*; 6 | pub use self::ifnull::*; 7 | pub use self::wide::*; 8 | -------------------------------------------------------------------------------- /ch10_exception/src/instructions/extended/mod.rs: -------------------------------------------------------------------------------- 1 | mod goto_w; 2 | mod ifnull; 3 | mod wide; 4 | 5 | pub use self::goto_w::*; 6 | pub use self::ifnull::*; 7 | pub use self::wide::*; 8 | -------------------------------------------------------------------------------- /ch01_cmd/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ch01_cmd" 3 | version = "0.1.0" 4 | authors = ["dxx "] 5 | edition = "2021" 6 | 7 | [dependencies] 8 | getopts = "0.2" 9 | -------------------------------------------------------------------------------- /ch05_instructions/src/instructions/extended/mod.rs: -------------------------------------------------------------------------------- 1 | mod goto_w; 2 | mod ifnull; 3 | mod wide; 4 | 5 | pub use self::goto_w::*; 6 | pub use self::ifnull::*; 7 | pub use self::wide::*; 8 | -------------------------------------------------------------------------------- /ch07_method_invoke/src/instructions/extended/mod.rs: -------------------------------------------------------------------------------- 1 | mod goto_w; 2 | mod ifnull; 3 | mod wide; 4 | 5 | pub use self::goto_w::*; 6 | pub use self::ifnull::*; 7 | pub use self::wide::*; 8 | -------------------------------------------------------------------------------- /ch08_array_string/src/instructions/extended/mod.rs: -------------------------------------------------------------------------------- 1 | mod goto_w; 2 | mod ifnull; 3 | mod wide; 4 | 5 | pub use self::goto_w::*; 6 | pub use self::ifnull::*; 7 | pub use self::wide::*; 8 | -------------------------------------------------------------------------------- /ch05_instructions/src/instructions/control/mod.rs: -------------------------------------------------------------------------------- 1 | mod goto; 2 | mod lookupswitch; 3 | mod tableswitch; 4 | 5 | pub use self::goto::*; 6 | pub use self::lookupswitch::*; 7 | pub use self::tableswitch::*; 8 | -------------------------------------------------------------------------------- /ch06_rtda_heap/src/instructions/control/mod.rs: -------------------------------------------------------------------------------- 1 | mod goto; 2 | mod lookupswitch; 3 | mod tableswitch; 4 | 5 | pub use self::goto::*; 6 | pub use self::lookupswitch::*; 7 | pub use self::tableswitch::*; 8 | -------------------------------------------------------------------------------- /java/example/.gitattributes: -------------------------------------------------------------------------------- 1 | # 2 | # https://help.github.com/articles/dealing-with-line-endings/ 3 | # 4 | # These are explicitly windows files and should use crlf 5 | *.bat text eol=crlf 6 | 7 | -------------------------------------------------------------------------------- /ch09_native/src/instructions/conversions/mod.rs: -------------------------------------------------------------------------------- 1 | mod d2x; 2 | mod f2x; 3 | mod i2x; 4 | mod l2x; 5 | 6 | pub use self::d2x::*; 7 | pub use self::f2x::*; 8 | pub use self::i2x::*; 9 | pub use self::l2x::*; 10 | -------------------------------------------------------------------------------- /ch06_rtda_heap/src/instructions/conversions/mod.rs: -------------------------------------------------------------------------------- 1 | mod d2x; 2 | mod f2x; 3 | mod i2x; 4 | mod l2x; 5 | 6 | pub use self::d2x::*; 7 | pub use self::f2x::*; 8 | pub use self::i2x::*; 9 | pub use self::l2x::*; 10 | -------------------------------------------------------------------------------- /ch10_exception/src/instructions/conversions/mod.rs: -------------------------------------------------------------------------------- 1 | mod d2x; 2 | mod f2x; 3 | mod i2x; 4 | mod l2x; 5 | 6 | pub use self::d2x::*; 7 | pub use self::f2x::*; 8 | pub use self::i2x::*; 9 | pub use self::l2x::*; 10 | -------------------------------------------------------------------------------- /ch05_instructions/src/instructions/conversions/mod.rs: -------------------------------------------------------------------------------- 1 | mod d2x; 2 | mod f2x; 3 | mod i2x; 4 | mod l2x; 5 | 6 | pub use self::d2x::*; 7 | pub use self::f2x::*; 8 | pub use self::i2x::*; 9 | pub use self::l2x::*; 10 | -------------------------------------------------------------------------------- /ch07_method_invoke/src/instructions/conversions/mod.rs: -------------------------------------------------------------------------------- 1 | mod d2x; 2 | mod f2x; 3 | mod i2x; 4 | mod l2x; 5 | 6 | pub use self::d2x::*; 7 | pub use self::f2x::*; 8 | pub use self::i2x::*; 9 | pub use self::l2x::*; 10 | -------------------------------------------------------------------------------- /ch08_array_string/src/instructions/conversions/mod.rs: -------------------------------------------------------------------------------- 1 | mod d2x; 2 | mod f2x; 3 | mod i2x; 4 | mod l2x; 5 | 6 | pub use self::d2x::*; 7 | pub use self::f2x::*; 8 | pub use self::i2x::*; 9 | pub use self::l2x::*; 10 | -------------------------------------------------------------------------------- /ch09_native/src/instructions/constants/mod.rs: -------------------------------------------------------------------------------- 1 | mod nop; 2 | mod consts; 3 | mod ldc; 4 | mod ipush; 5 | 6 | pub use self::nop::*; 7 | pub use self::consts::*; 8 | pub use self::ldc::*; 9 | pub use self::ipush::*; 10 | -------------------------------------------------------------------------------- /ch06_rtda_heap/src/instructions/constants/mod.rs: -------------------------------------------------------------------------------- 1 | mod nop; 2 | mod consts; 3 | mod ldc; 4 | mod ipush; 5 | 6 | pub use self::nop::*; 7 | pub use self::consts::*; 8 | pub use self::ldc::*; 9 | pub use self::ipush::*; 10 | -------------------------------------------------------------------------------- /ch07_method_invoke/src/instructions/constants/mod.rs: -------------------------------------------------------------------------------- 1 | mod nop; 2 | mod consts; 3 | mod ldc; 4 | mod ipush; 5 | 6 | pub use self::nop::*; 7 | pub use self::consts::*; 8 | pub use self::ldc::*; 9 | pub use self::ipush::*; 10 | -------------------------------------------------------------------------------- /ch08_array_string/src/instructions/constants/mod.rs: -------------------------------------------------------------------------------- 1 | mod nop; 2 | mod consts; 3 | mod ldc; 4 | mod ipush; 5 | 6 | pub use self::nop::*; 7 | pub use self::consts::*; 8 | pub use self::ldc::*; 9 | pub use self::ipush::*; 10 | -------------------------------------------------------------------------------- /ch10_exception/src/instructions/constants/mod.rs: -------------------------------------------------------------------------------- 1 | mod nop; 2 | mod consts; 3 | mod ldc; 4 | mod ipush; 5 | 6 | pub use self::nop::*; 7 | pub use self::consts::*; 8 | pub use self::ldc::*; 9 | pub use self::ipush::*; 10 | -------------------------------------------------------------------------------- /java/example/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore Gradle project-specific cache directory 2 | .gradle 3 | 4 | # Ignore Gradle build output directory 5 | build 6 | 7 | out 8 | 9 | # IntelliJ IDEA 10 | .idea 11 | *.iws 12 | *.iml 13 | *.ipr 14 | -------------------------------------------------------------------------------- /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.x86_64-unknown-linux-musl] 2 | linker = "rust-lld" 3 | rustflags = ["-C", "linker-flavor=ld.lld"] 4 | 5 | [target.x86_64-pc-windows-gnu] 6 | linker = "x86_64-w64-mingw32-gcc" 7 | ar = "x86_64-w64-mingw32-gcc-ar" 8 | -------------------------------------------------------------------------------- /ch04_rtda/src/rtda.rs: -------------------------------------------------------------------------------- 1 | mod object; 2 | mod thread; 3 | mod jvm_stack; 4 | mod frame; 5 | mod local_vars; 6 | mod operand_stack; 7 | 8 | pub use self::frame::*; 9 | pub use self::local_vars::*; 10 | pub use self::operand_stack::*; 11 | -------------------------------------------------------------------------------- /ch03_classfile/src/types.rs: -------------------------------------------------------------------------------- 1 | use std::result::Result as StdResult; 2 | use std::rc::Rc; 3 | use std::cell::RefCell; 4 | 5 | /// Type alias 6 | 7 | pub type Result = StdResult; 8 | 9 | pub type RcRefCell = Rc>; 10 | -------------------------------------------------------------------------------- /java/example/src/main/java/jvmrust/ch01/HelloWorld.java: -------------------------------------------------------------------------------- 1 | package jvmrust.ch01; 2 | 3 | public class HelloWorld { 4 | 5 | public static void main(String[] args) { 6 | System.out.println("Hello, world!"); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /ch04_rtda/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ch04_rtda" 3 | version = "0.1.0" 4 | authors = ["dxx "] 5 | edition = "2021" 6 | 7 | [dependencies] 8 | getopts = "0.2" 9 | zip = { version = "0.5", default-features = false, features = ["deflate"] } 10 | -------------------------------------------------------------------------------- /ch06_rtda_heap/src/instructions/loads/mod.rs: -------------------------------------------------------------------------------- 1 | mod aload; 2 | mod dload; 3 | mod fload; 4 | mod iload; 5 | mod lload; 6 | 7 | pub use self::aload::*; 8 | pub use self::dload::*; 9 | pub use self::fload::*; 10 | pub use self::iload::*; 11 | pub use self::lload::*; 12 | -------------------------------------------------------------------------------- /java/example/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /ch05_instructions/src/instructions/loads/mod.rs: -------------------------------------------------------------------------------- 1 | mod aload; 2 | mod dload; 3 | mod fload; 4 | mod iload; 5 | mod lload; 6 | 7 | pub use self::aload::*; 8 | pub use self::dload::*; 9 | pub use self::fload::*; 10 | pub use self::iload::*; 11 | pub use self::lload::*; 12 | -------------------------------------------------------------------------------- /ch05_instructions/src/rtda.rs: -------------------------------------------------------------------------------- 1 | mod object; 2 | mod thread; 3 | mod jvm_stack; 4 | mod frame; 5 | mod local_vars; 6 | mod operand_stack; 7 | 8 | pub use self::thread::*; 9 | pub use self::frame::*; 10 | pub use self::local_vars::*; 11 | pub use self::operand_stack::*; 12 | -------------------------------------------------------------------------------- /ch07_method_invoke/src/instructions/loads/mod.rs: -------------------------------------------------------------------------------- 1 | mod aload; 2 | mod dload; 3 | mod fload; 4 | mod iload; 5 | mod lload; 6 | 7 | pub use self::aload::*; 8 | pub use self::dload::*; 9 | pub use self::fload::*; 10 | pub use self::iload::*; 11 | pub use self::lload::*; 12 | -------------------------------------------------------------------------------- /ch02_classpath/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ch02_classpath" 3 | version = "0.1.0" 4 | authors = ["dxx "] 5 | edition = "2021" 6 | 7 | [dependencies] 8 | getopts = "0.2" 9 | zip = { version = "0.5", default-features = false, features = ["deflate"] } 10 | -------------------------------------------------------------------------------- /ch03_classfile/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ch03_classfile" 3 | version = "0.1.0" 4 | authors = ["dxx "] 5 | edition = "2021" 6 | 7 | [dependencies] 8 | getopts = "0.2" 9 | zip = { version = "0.5", default-features = false, features = ["deflate"] } 10 | -------------------------------------------------------------------------------- /ch06_rtda_heap/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ch06_rtda_heap" 3 | version = "0.1.0" 4 | authors = ["dxx "] 5 | edition = "2021" 6 | 7 | [dependencies] 8 | getopts = "0.2" 9 | zip = { version = "0.5", default-features = false, features = ["deflate"] } 10 | -------------------------------------------------------------------------------- /ch06_rtda_heap/src/instructions/stores/mod.rs: -------------------------------------------------------------------------------- 1 | mod astore; 2 | mod dstore; 3 | mod fstore; 4 | mod istore; 5 | mod lstore; 6 | 7 | pub use self::astore::*; 8 | pub use self::dstore::*; 9 | pub use self::fstore::*; 10 | pub use self::istore::*; 11 | pub use self::lstore::*; 12 | -------------------------------------------------------------------------------- /ch05_instructions/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ch05_instructions" 3 | version = "0.1.0" 4 | authors = ["dxx "] 5 | edition = "2021" 6 | 7 | [dependencies] 8 | getopts = "0.2" 9 | zip = { version = "0.5", default-features = false, features = ["deflate"] } 10 | -------------------------------------------------------------------------------- /ch05_instructions/src/instructions/stores/mod.rs: -------------------------------------------------------------------------------- 1 | mod astore; 2 | mod dstore; 3 | mod fstore; 4 | mod istore; 5 | mod lstore; 6 | 7 | pub use self::astore::*; 8 | pub use self::dstore::*; 9 | pub use self::fstore::*; 10 | pub use self::istore::*; 11 | pub use self::lstore::*; 12 | -------------------------------------------------------------------------------- /ch07_method_invoke/src/instructions/stores/mod.rs: -------------------------------------------------------------------------------- 1 | mod astore; 2 | mod dstore; 3 | mod fstore; 4 | mod istore; 5 | mod lstore; 6 | 7 | pub use self::astore::*; 8 | pub use self::dstore::*; 9 | pub use self::fstore::*; 10 | pub use self::istore::*; 11 | pub use self::lstore::*; 12 | -------------------------------------------------------------------------------- /ch09_native/src/instructions/control/mod.rs: -------------------------------------------------------------------------------- 1 | mod goto; 2 | mod lookupswitch; 3 | mod tableswitch; 4 | 5 | #[path = "return.rs"] 6 | mod _return; 7 | 8 | pub use self::goto::*; 9 | pub use self::lookupswitch::*; 10 | pub use self::tableswitch::*; 11 | pub use self::_return::*; 12 | -------------------------------------------------------------------------------- /ch07_method_invoke/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ch07_method_invoke" 3 | version = "0.1.0" 4 | authors = ["dxx "] 5 | edition = "2021" 6 | 7 | [dependencies] 8 | getopts = "0.2" 9 | zip = { version = "0.5", default-features = false, features = ["deflate"] } 10 | -------------------------------------------------------------------------------- /ch07_method_invoke/src/instructions/control/mod.rs: -------------------------------------------------------------------------------- 1 | mod goto; 2 | mod lookupswitch; 3 | mod tableswitch; 4 | 5 | #[path = "return.rs"] 6 | mod _return; 7 | 8 | pub use self::goto::*; 9 | pub use self::lookupswitch::*; 10 | pub use self::tableswitch::*; 11 | pub use self::_return::*; 12 | -------------------------------------------------------------------------------- /ch08_array_string/src/instructions/control/mod.rs: -------------------------------------------------------------------------------- 1 | mod goto; 2 | mod lookupswitch; 3 | mod tableswitch; 4 | 5 | #[path = "return.rs"] 6 | mod _return; 7 | 8 | pub use self::goto::*; 9 | pub use self::lookupswitch::*; 10 | pub use self::tableswitch::*; 11 | pub use self::_return::*; 12 | -------------------------------------------------------------------------------- /ch10_exception/src/instructions/control/mod.rs: -------------------------------------------------------------------------------- 1 | mod goto; 2 | mod lookupswitch; 3 | mod tableswitch; 4 | 5 | #[path = "return.rs"] 6 | mod _return; 7 | 8 | pub use self::goto::*; 9 | pub use self::lookupswitch::*; 10 | pub use self::tableswitch::*; 11 | pub use self::_return::*; 12 | -------------------------------------------------------------------------------- /java/example/src/main/java/jvmrust/ch08/PrintArgs.java: -------------------------------------------------------------------------------- 1 | package jvmrust.ch08; 2 | 3 | public class PrintArgs { 4 | 5 | public static void main(String[] args) { 6 | for (String arg : args) { 7 | System.out.println(arg); 8 | } 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /ch09_native/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ch09_native" 3 | version = "0.1.0" 4 | authors = ["dxx "] 5 | edition = "2021" 6 | 7 | [dependencies] 8 | getopts = "0.2" 9 | zip = { version = "0.5", default-features = false, features = ["deflate"] } 10 | once_cell = "1.10.0" 11 | -------------------------------------------------------------------------------- /ch10_exception/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ch10_exception" 3 | version = "0.1.0" 4 | authors = ["dxx "] 5 | edition = "2021" 6 | 7 | [dependencies] 8 | getopts = "0.2" 9 | zip = { version = "0.5", default-features = false, features = ["deflate"] } 10 | once_cell = "1.10.0" 11 | -------------------------------------------------------------------------------- /ch04_rtda/src/types.rs: -------------------------------------------------------------------------------- 1 | use std::result::Result as StdResult; 2 | use std::rc::Rc; 3 | use std::cell::RefCell; 4 | 5 | /// Type alias 6 | 7 | pub type Result = StdResult; 8 | 9 | pub type RcRefCell = Rc>; 10 | 11 | pub type OptionalRcRefCell = Option>>; 12 | -------------------------------------------------------------------------------- /ch06_rtda_heap/src/rtda/heap/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod access_flags; 2 | pub mod class; 3 | pub mod class_loader; 4 | pub mod constant_pool; 5 | pub mod cp_classref; 6 | pub mod cp_fieldref; 7 | pub mod cp_methodref; 8 | pub mod cp_interface_methodref; 9 | pub mod field; 10 | pub mod method; 11 | pub mod slots; 12 | -------------------------------------------------------------------------------- /ch06_rtda_heap/src/types.rs: -------------------------------------------------------------------------------- 1 | use std::result::Result as StdResult; 2 | use std::rc::Rc; 3 | use std::cell::RefCell; 4 | 5 | /// Type alias 6 | 7 | pub type Result = StdResult; 8 | 9 | pub type RcRefCell = Rc>; 10 | 11 | pub type OptionalRcRefCell = Option>; 12 | -------------------------------------------------------------------------------- /ch09_native/src/types.rs: -------------------------------------------------------------------------------- 1 | use std::result::Result as StdResult; 2 | use std::rc::Rc; 3 | use std::cell::RefCell; 4 | 5 | /// Type alias 6 | 7 | pub type Result = StdResult; 8 | 9 | pub type RcRefCell = Rc>; 10 | 11 | pub type OptionalRcRefCell = Option>; 12 | -------------------------------------------------------------------------------- /ch10_exception/src/types.rs: -------------------------------------------------------------------------------- 1 | use std::result::Result as StdResult; 2 | use std::rc::Rc; 3 | use std::cell::RefCell; 4 | 5 | /// Type alias 6 | 7 | pub type Result = StdResult; 8 | 9 | pub type RcRefCell = Rc>; 10 | 11 | pub type OptionalRcRefCell = Option>; 12 | -------------------------------------------------------------------------------- /ch05_instructions/src/instructions/base/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod bytecode_reader; 2 | pub mod instruction; 3 | 4 | use super::super::rtda::Frame; 5 | 6 | pub fn branch(frame: &mut Frame, offset: i64) { 7 | let pc = frame.thread().borrow().pc(); 8 | let next_pc = pc + offset; 9 | frame.set_next_pc(next_pc); 10 | } 11 | -------------------------------------------------------------------------------- /ch05_instructions/src/types.rs: -------------------------------------------------------------------------------- 1 | use std::result::Result as StdResult; 2 | use std::rc::Rc; 3 | use std::cell::RefCell; 4 | 5 | /// Type alias 6 | 7 | pub type Result = StdResult; 8 | 9 | pub type RcRefCell = Rc>; 10 | 11 | pub type OptionalRcRefCell = Option>; 12 | -------------------------------------------------------------------------------- /ch06_rtda_heap/src/instructions/base/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod bytecode_reader; 2 | pub mod instruction; 3 | 4 | use super::super::rtda::Frame; 5 | 6 | pub fn branch(frame: &mut Frame, offset: i64) { 7 | let pc = frame.thread().borrow().pc(); 8 | let next_pc = pc + offset; 9 | frame.set_next_pc(next_pc); 10 | } 11 | -------------------------------------------------------------------------------- /ch07_method_invoke/README.md: -------------------------------------------------------------------------------- 1 | ### Chapter 7: 方法调用和返回 2 | 3 | #### 编译: 4 | 5 | ```shell 6 | jvm-rust ❯ cargo build -p ch07_method_invoke 7 | ``` 8 | 9 | #### 运行: 10 | 11 | ```shell 12 | jvm-rust ❯ ./target/debug/ch07_method_invoke -cp "/Users/dxx/Desktop" jvmrust.ch07.FibonacciTest 13 | 832040 14 | ``` 15 | -------------------------------------------------------------------------------- /ch07_method_invoke/src/types.rs: -------------------------------------------------------------------------------- 1 | use std::result::Result as StdResult; 2 | use std::rc::Rc; 3 | use std::cell::RefCell; 4 | 5 | /// Type alias 6 | 7 | pub type Result = StdResult; 8 | 9 | pub type RcRefCell = Rc>; 10 | 11 | pub type OptionalRcRefCell = Option>; 12 | -------------------------------------------------------------------------------- /ch08_array_string/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ch08_array_string" 3 | version = "0.1.0" 4 | authors = ["dxx "] 5 | edition = "2021" 6 | 7 | [dependencies] 8 | getopts = "0.2" 9 | zip = { version = "0.5", default-features = false, features = ["deflate"] } 10 | once_cell = "1.10.0" 11 | -------------------------------------------------------------------------------- /ch08_array_string/src/types.rs: -------------------------------------------------------------------------------- 1 | use std::result::Result as StdResult; 2 | use std::rc::Rc; 3 | use std::cell::RefCell; 4 | 5 | /// Type alias 6 | 7 | pub type Result = StdResult; 8 | 9 | pub type RcRefCell = Rc>; 10 | 11 | pub type OptionalRcRefCell = Option>; 12 | -------------------------------------------------------------------------------- /ch09_native/src/instructions/loads/mod.rs: -------------------------------------------------------------------------------- 1 | mod aload; 2 | mod dload; 3 | mod fload; 4 | mod iload; 5 | mod lload; 6 | mod xaload; 7 | 8 | pub use self::aload::*; 9 | pub use self::dload::*; 10 | pub use self::fload::*; 11 | pub use self::iload::*; 12 | pub use self::lload::*; 13 | pub use self::xaload::*; 14 | -------------------------------------------------------------------------------- /ch10_exception/src/instructions/loads/mod.rs: -------------------------------------------------------------------------------- 1 | mod aload; 2 | mod dload; 3 | mod fload; 4 | mod iload; 5 | mod lload; 6 | mod xaload; 7 | 8 | pub use self::aload::*; 9 | pub use self::dload::*; 10 | pub use self::fload::*; 11 | pub use self::iload::*; 12 | pub use self::lload::*; 13 | pub use self::xaload::*; 14 | -------------------------------------------------------------------------------- /ch08_array_string/src/instructions/loads/mod.rs: -------------------------------------------------------------------------------- 1 | mod aload; 2 | mod dload; 3 | mod fload; 4 | mod iload; 5 | mod lload; 6 | mod xaload; 7 | 8 | pub use self::aload::*; 9 | pub use self::dload::*; 10 | pub use self::fload::*; 11 | pub use self::iload::*; 12 | pub use self::lload::*; 13 | pub use self::xaload::*; 14 | -------------------------------------------------------------------------------- /ch09_native/src/instructions/comparisons/mod.rs: -------------------------------------------------------------------------------- 1 | mod dcmp; 2 | mod fcmp; 3 | mod if_acmp; 4 | mod if_icmp; 5 | mod ifcond; 6 | mod lcmp; 7 | 8 | pub use self::dcmp::*; 9 | pub use self::fcmp::*; 10 | pub use self::if_acmp::*; 11 | pub use self::if_icmp::*; 12 | pub use self::ifcond::*; 13 | pub use self::lcmp::*; 14 | -------------------------------------------------------------------------------- /ch06_rtda_heap/src/instructions/comparisons/mod.rs: -------------------------------------------------------------------------------- 1 | mod dcmp; 2 | mod fcmp; 3 | mod if_acmp; 4 | mod if_icmp; 5 | mod ifcond; 6 | mod lcmp; 7 | 8 | pub use self::dcmp::*; 9 | pub use self::fcmp::*; 10 | pub use self::if_acmp::*; 11 | pub use self::if_icmp::*; 12 | pub use self::ifcond::*; 13 | pub use self::lcmp::*; 14 | -------------------------------------------------------------------------------- /ch09_native/src/instructions/stores/mod.rs: -------------------------------------------------------------------------------- 1 | mod astore; 2 | mod dstore; 3 | mod fstore; 4 | mod istore; 5 | mod lstore; 6 | mod xastore; 7 | 8 | pub use self::astore::*; 9 | pub use self::dstore::*; 10 | pub use self::fstore::*; 11 | pub use self::istore::*; 12 | pub use self::lstore::*; 13 | pub use self::xastore::*; 14 | -------------------------------------------------------------------------------- /ch10_exception/src/instructions/comparisons/mod.rs: -------------------------------------------------------------------------------- 1 | mod dcmp; 2 | mod fcmp; 3 | mod if_acmp; 4 | mod if_icmp; 5 | mod ifcond; 6 | mod lcmp; 7 | 8 | pub use self::dcmp::*; 9 | pub use self::fcmp::*; 10 | pub use self::if_acmp::*; 11 | pub use self::if_icmp::*; 12 | pub use self::ifcond::*; 13 | pub use self::lcmp::*; 14 | -------------------------------------------------------------------------------- /ch05_instructions/src/instructions/comparisons/mod.rs: -------------------------------------------------------------------------------- 1 | mod dcmp; 2 | mod fcmp; 3 | mod if_acmp; 4 | mod if_icmp; 5 | mod ifcond; 6 | mod lcmp; 7 | 8 | pub use self::dcmp::*; 9 | pub use self::fcmp::*; 10 | pub use self::if_acmp::*; 11 | pub use self::if_icmp::*; 12 | pub use self::ifcond::*; 13 | pub use self::lcmp::*; 14 | -------------------------------------------------------------------------------- /ch07_method_invoke/src/instructions/comparisons/mod.rs: -------------------------------------------------------------------------------- 1 | mod dcmp; 2 | mod fcmp; 3 | mod if_acmp; 4 | mod if_icmp; 5 | mod ifcond; 6 | mod lcmp; 7 | 8 | pub use self::dcmp::*; 9 | pub use self::fcmp::*; 10 | pub use self::if_acmp::*; 11 | pub use self::if_icmp::*; 12 | pub use self::ifcond::*; 13 | pub use self::lcmp::*; 14 | -------------------------------------------------------------------------------- /ch08_array_string/src/instructions/comparisons/mod.rs: -------------------------------------------------------------------------------- 1 | mod dcmp; 2 | mod fcmp; 3 | mod if_acmp; 4 | mod if_icmp; 5 | mod ifcond; 6 | mod lcmp; 7 | 8 | pub use self::dcmp::*; 9 | pub use self::fcmp::*; 10 | pub use self::if_acmp::*; 11 | pub use self::if_icmp::*; 12 | pub use self::ifcond::*; 13 | pub use self::lcmp::*; 14 | -------------------------------------------------------------------------------- /ch10_exception/src/instructions/stores/mod.rs: -------------------------------------------------------------------------------- 1 | mod astore; 2 | mod dstore; 3 | mod fstore; 4 | mod istore; 5 | mod lstore; 6 | mod xastore; 7 | 8 | pub use self::astore::*; 9 | pub use self::dstore::*; 10 | pub use self::fstore::*; 11 | pub use self::istore::*; 12 | pub use self::lstore::*; 13 | pub use self::xastore::*; 14 | -------------------------------------------------------------------------------- /ch06_rtda_heap/src/instructions/constants/nop.rs: -------------------------------------------------------------------------------- 1 | use super::super::instruction::Instruction; 2 | use super::super::super::rtda::Frame; 3 | 4 | #[derive(Default, Debug)] 5 | pub struct NOP; 6 | 7 | impl Instruction for NOP { 8 | fn execute(&mut self, frame: &mut Frame) { 9 | // Really do nothing 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /ch08_array_string/src/instructions/stores/mod.rs: -------------------------------------------------------------------------------- 1 | mod astore; 2 | mod dstore; 3 | mod fstore; 4 | mod istore; 5 | mod lstore; 6 | mod xastore; 7 | 8 | pub use self::astore::*; 9 | pub use self::dstore::*; 10 | pub use self::fstore::*; 11 | pub use self::istore::*; 12 | pub use self::lstore::*; 13 | pub use self::xastore::*; 14 | -------------------------------------------------------------------------------- /ch05_instructions/src/instructions/constants/nop.rs: -------------------------------------------------------------------------------- 1 | use super::super::instruction::Instruction; 2 | use super::super::super::rtda::Frame; 3 | 4 | #[derive(Default, Debug)] 5 | pub struct NOP; 6 | 7 | impl Instruction for NOP { 8 | fn execute(&mut self, frame: &mut Frame) { 9 | // Really do nothing 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /ch07_method_invoke/src/instructions/constants/nop.rs: -------------------------------------------------------------------------------- 1 | use super::super::instruction::Instruction; 2 | use super::super::super::rtda::Frame; 3 | 4 | #[derive(Default, Debug)] 5 | pub struct NOP; 6 | 7 | impl Instruction for NOP { 8 | fn execute(&mut self, frame: &mut Frame) { 9 | // Really do nothing 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /ch09_native/src/rtda.rs: -------------------------------------------------------------------------------- 1 | mod object; 2 | mod thread; 3 | mod jvm_stack; 4 | mod frame; 5 | mod local_vars; 6 | mod operand_stack; 7 | mod heap; 8 | 9 | pub use self::object::*; 10 | pub use self::thread::*; 11 | pub use self::frame::*; 12 | pub use self::local_vars::*; 13 | pub use self::operand_stack::*; 14 | pub use self::heap::*; 15 | -------------------------------------------------------------------------------- /ch06_rtda_heap/src/rtda.rs: -------------------------------------------------------------------------------- 1 | mod object; 2 | mod thread; 3 | mod jvm_stack; 4 | mod frame; 5 | mod local_vars; 6 | mod operand_stack; 7 | mod heap; 8 | 9 | pub use self::object::*; 10 | pub use self::thread::*; 11 | pub use self::frame::*; 12 | pub use self::local_vars::*; 13 | pub use self::operand_stack::*; 14 | pub use self::heap::*; 15 | -------------------------------------------------------------------------------- /ch10_exception/src/rtda.rs: -------------------------------------------------------------------------------- 1 | mod object; 2 | mod thread; 3 | mod jvm_stack; 4 | mod frame; 5 | mod local_vars; 6 | mod operand_stack; 7 | mod heap; 8 | 9 | pub use self::object::*; 10 | pub use self::thread::*; 11 | pub use self::frame::*; 12 | pub use self::local_vars::*; 13 | pub use self::operand_stack::*; 14 | pub use self::heap::*; 15 | -------------------------------------------------------------------------------- /java/example/src/main/java/jvmrust/ch05/GaussTest.java: -------------------------------------------------------------------------------- 1 | package jvmrust.ch05; 2 | 3 | public class GaussTest { 4 | 5 | public static void main(String[] args) { 6 | int sum = 0; 7 | for (int i = 1; i <= 100; i++) { 8 | sum += i; 9 | } 10 | System.out.println(sum); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /ch07_method_invoke/src/rtda.rs: -------------------------------------------------------------------------------- 1 | mod object; 2 | mod thread; 3 | mod jvm_stack; 4 | mod frame; 5 | mod local_vars; 6 | mod operand_stack; 7 | mod heap; 8 | 9 | pub use self::object::*; 10 | pub use self::thread::*; 11 | pub use self::frame::*; 12 | pub use self::local_vars::*; 13 | pub use self::operand_stack::*; 14 | pub use self::heap::*; 15 | -------------------------------------------------------------------------------- /ch08_array_string/src/rtda.rs: -------------------------------------------------------------------------------- 1 | mod object; 2 | mod thread; 3 | mod jvm_stack; 4 | mod frame; 5 | mod local_vars; 6 | mod operand_stack; 7 | mod heap; 8 | 9 | pub use self::object::*; 10 | pub use self::thread::*; 11 | pub use self::frame::*; 12 | pub use self::local_vars::*; 13 | pub use self::operand_stack::*; 14 | pub use self::heap::*; 15 | -------------------------------------------------------------------------------- /java/example/src/main/java/jvmrust/ch08/MultianewarrayDemo.java: -------------------------------------------------------------------------------- 1 | package jvmrust.ch08; 2 | 3 | public class MultianewarrayDemo { 4 | 5 | public static void main(String[] args) { 6 | new MultianewarrayDemo().test(); 7 | } 8 | 9 | public void test() { 10 | int[][][] x = new int[3][4][5]; 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /java/example/src/main/java/jvmrust/ch09/StringBuilderTest.java: -------------------------------------------------------------------------------- 1 | package jvmrust.ch09; 2 | 3 | public class StringBuilderTest { 4 | 5 | public static void main(String[] args) { 6 | String hello = "hello,"; 7 | String world = "world!"; 8 | String str = hello + world; 9 | System.out.println(str); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /ch01_cmd/README.md: -------------------------------------------------------------------------------- 1 | ### Chapter 1: 命令行工具 2 | 3 | #### 编译: 4 | 5 | ```shell 6 | jvm-rust ❯ cargo build -p ch01_cmd --release 7 | ``` 8 | 9 | #### 运行: 10 | 11 | ```shell 12 | jvm-rust ❯ ./target/release/ch01_cmd -help 13 | Usage: ./target/release/ch01_cmd [-options] class [args...] 14 | 15 | jvm-rust ❯ ./target/release/ch01_cmd -version 16 | version 0.0.1 17 | ``` 18 | -------------------------------------------------------------------------------- /ch07_method_invoke/src/rtda/heap/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod access_flags; 2 | pub mod class; 3 | pub mod class_loader; 4 | pub mod constant_pool; 5 | pub mod cp_classref; 6 | pub mod cp_fieldref; 7 | pub mod cp_methodref; 8 | pub mod cp_interface_methodref; 9 | pub mod field; 10 | pub mod method; 11 | pub mod method_descriptor; 12 | pub mod method_lookup; 13 | pub mod slots; 14 | -------------------------------------------------------------------------------- /ch09_native/src/instructions/constants/nop.rs: -------------------------------------------------------------------------------- 1 | use super::super::instruction::Instruction; 2 | use super::super::super::rtda::Frame; 3 | 4 | #[derive(Default, Debug)] 5 | pub struct NOP; 6 | 7 | impl Instruction for NOP { 8 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 9 | // Really do nothing 10 | Ok(()) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /ch10_exception/src/instructions/constants/nop.rs: -------------------------------------------------------------------------------- 1 | use super::super::instruction::Instruction; 2 | use super::super::super::rtda::Frame; 3 | 4 | #[derive(Default, Debug)] 5 | pub struct NOP; 6 | 7 | impl Instruction for NOP { 8 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 9 | // Really do nothing 10 | Ok(()) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /ch08_array_string/src/instructions/constants/nop.rs: -------------------------------------------------------------------------------- 1 | use super::super::instruction::Instruction; 2 | use super::super::super::rtda::Frame; 3 | 4 | #[derive(Default, Debug)] 5 | pub struct NOP; 6 | 7 | impl Instruction for NOP { 8 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 9 | // Really do nothing 10 | Ok(()) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /java/example/src/main/java/jvmrust/ch06/FieldTest.java: -------------------------------------------------------------------------------- 1 | package jvmrust.ch06; 2 | 3 | public class FieldTest { 4 | 5 | public static class Inner { 6 | private int x; 7 | } 8 | 9 | public static void main(String[] args) { 10 | Inner inner = new Inner(); 11 | inner.x = 100; 12 | System.out.println(inner.x); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 7 | Cargo.lock 8 | 9 | # These are backup files generated by rustfmt 10 | **/*.rs.bk 11 | 12 | .DS_Store 13 | -------------------------------------------------------------------------------- /java/example/src/main/java/jvmrust/ch04/Math.java: -------------------------------------------------------------------------------- 1 | package jvmrust.ch04; 2 | 3 | public class Math { 4 | 5 | public static void main(String[] args) { 6 | System.out.println(circumference(1.6f)); 7 | } 8 | 9 | public static float circumference(float r) { 10 | float pi = 3.14f; 11 | float c = 2 * pi * r; 12 | return c; 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /java/example/src/main/java/jvmrust/ch05/ShTest.java: -------------------------------------------------------------------------------- 1 | package jvmrust.ch05; 2 | 3 | public class ShTest { 4 | 5 | public static void main(String[] args) { 6 | int x = -1; 7 | System.out.println(Integer.toBinaryString(x)); 8 | System.out.println(Integer.toBinaryString(x >> 8)); 9 | System.out.println(Integer.toBinaryString(x >>> 8)); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /java/example/src/main/java/jvmrust/ch10/StackTraceTest.java: -------------------------------------------------------------------------------- 1 | package jvmrust.ch10; 2 | 3 | public class StackTraceTest { 4 | 5 | public static void main(String[] args) { 6 | foo(); 7 | } 8 | 9 | private static void foo() { 10 | bar(); 11 | } 12 | 13 | private static void bar() { 14 | throw new RuntimeException("OH!"); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /ch04_rtda/README.md: -------------------------------------------------------------------------------- 1 | ### Chapter 4: 运行时数据区 2 | 3 | #### 编译: 4 | 5 | ```shell 6 | jvm-rust ❯ cargo build -p ch04_rtda 7 | ``` 8 | 9 | #### 运行: 10 | 11 | ```shell 12 | jvm-rust ❯ ./target/debug/ch04_rtda test 13 | 100 14 | -100 15 | 2997924580 16 | -2997924580 17 | 3.1415925 18 | 2.71828182845 19 | None 20 | None 21 | 2.71828182845 22 | 3.1415925 23 | -2997924580 24 | 2997924580 25 | -100 26 | 100 27 | ``` 28 | -------------------------------------------------------------------------------- /ch06_rtda_heap/src/instructions/base/instruction.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Debug; 2 | 3 | use crate::rtda::Frame; 4 | use super::bytecode_reader::BytecodeReader; 5 | 6 | pub trait Instruction: Debug { 7 | // fn fetch_operands(&mut self, reader: &mut BytecodeReader); 8 | fn fetch_operands(&mut self, reader: &mut BytecodeReader) { 9 | // Nothing to do 10 | } 11 | 12 | fn execute(&mut self, frame: &mut Frame); 13 | } 14 | -------------------------------------------------------------------------------- /java/example/src/main/java/jvmrust/ch06/Circle.java: -------------------------------------------------------------------------------- 1 | package jvmrust.ch06; 2 | 3 | public class Circle { 4 | 5 | public static float PI; 6 | 7 | public float r; 8 | 9 | public static void main(String[] args) { 10 | Circle.PI = 3.14f; 11 | Circle c = new Circle(); 12 | c.r = 5.5f; 13 | 14 | float area = Circle.PI * c.r * c.r; 15 | System.out.println(area); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /ch05_instructions/src/instructions/base/instruction.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Debug; 2 | 3 | use crate::rtda::Frame; 4 | use super::bytecode_reader::BytecodeReader; 5 | 6 | pub trait Instruction: Debug { 7 | // fn fetch_operands(&mut self, reader: &mut BytecodeReader); 8 | fn fetch_operands(&mut self, reader: &mut BytecodeReader) { 9 | // Nothing to do 10 | } 11 | 12 | fn execute(&mut self, frame: &mut Frame); 13 | } 14 | -------------------------------------------------------------------------------- /ch07_method_invoke/src/instructions/base/instruction.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Debug; 2 | 3 | use crate::rtda::Frame; 4 | use super::bytecode_reader::BytecodeReader; 5 | 6 | pub trait Instruction: Debug { 7 | // fn fetch_operands(&mut self, reader: &mut BytecodeReader); 8 | fn fetch_operands(&mut self, reader: &mut BytecodeReader) { 9 | // Nothing to do 10 | } 11 | 12 | fn execute(&mut self, frame: &mut Frame); 13 | } 14 | -------------------------------------------------------------------------------- /java/example/src/main/java/jvmrust/ch07/InvokeInterfaceTest.java: -------------------------------------------------------------------------------- 1 | package jvmrust.ch07; 2 | 3 | public class InvokeInterfaceTest { 4 | 5 | public static void main(String[] args) { 6 | Vector v = new Vector3D(3.1, 3.2, 3.3); 7 | v.multiply(3); 8 | 9 | Vector3D v3 = (Vector3D) v; 10 | System.out.println(v3.x); 11 | System.out.println(v3.y); 12 | System.out.println(v3.z); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /ch09_native/src/instructions/base/instruction.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Debug; 2 | 3 | use crate::rtda::Frame; 4 | use super::bytecode_reader::BytecodeReader; 5 | 6 | pub trait Instruction: Debug { 7 | // fn fetch_operands(&mut self, reader: &mut BytecodeReader); 8 | fn fetch_operands(&mut self, reader: &mut BytecodeReader) { 9 | // Nothing to do 10 | } 11 | 12 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()>; 13 | } 14 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "jvm-rust" 3 | version = "0.1.0" 4 | authors = ["dxx "] 5 | edition = "2021" 6 | 7 | [workspace] 8 | members = [ 9 | "ch01_cmd", 10 | "ch02_classpath", 11 | "ch03_classfile", 12 | "ch04_rtda", 13 | "ch05_instructions", 14 | "ch06_rtda_heap", 15 | "ch07_method_invoke", 16 | "ch08_array_string", 17 | "ch09_native", 18 | "ch10_exception", 19 | ] 20 | 21 | [dependencies] 22 | -------------------------------------------------------------------------------- /ch08_array_string/src/instructions/base/instruction.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Debug; 2 | 3 | use crate::rtda::Frame; 4 | use super::bytecode_reader::BytecodeReader; 5 | 6 | pub trait Instruction: Debug { 7 | // fn fetch_operands(&mut self, reader: &mut BytecodeReader); 8 | fn fetch_operands(&mut self, reader: &mut BytecodeReader) { 9 | // Nothing to do 10 | } 11 | 12 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()>; 13 | } 14 | -------------------------------------------------------------------------------- /ch10_exception/src/instructions/base/instruction.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Debug; 2 | 3 | use crate::rtda::Frame; 4 | use super::bytecode_reader::BytecodeReader; 5 | 6 | pub trait Instruction: Debug { 7 | // fn fetch_operands(&mut self, reader: &mut BytecodeReader); 8 | fn fetch_operands(&mut self, reader: &mut BytecodeReader) { 9 | // Nothing to do 10 | } 11 | 12 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()>; 13 | } 14 | -------------------------------------------------------------------------------- /ch09_native/src/rtda/heap/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod access_flags; 2 | pub mod array_class; 3 | pub mod array_object; 4 | pub mod class; 5 | pub mod class_loader; 6 | pub mod class_name_helper; 7 | pub mod constant_pool; 8 | pub mod cp_classref; 9 | pub mod cp_fieldref; 10 | pub mod cp_methodref; 11 | pub mod cp_interface_methodref; 12 | pub mod field; 13 | pub mod method; 14 | pub mod method_descriptor; 15 | pub mod method_lookup; 16 | pub mod slots; 17 | pub mod string_pool; 18 | -------------------------------------------------------------------------------- /java/example/src/main/java/jvmrust/ch09/ArrayListTest.java: -------------------------------------------------------------------------------- 1 | package jvmrust.ch09; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class ArrayListTest { 7 | 8 | public static void main(String[] args) { 9 | List strs = new ArrayList<>(); 10 | strs.add("hello"); 11 | strs.add("world"); 12 | for (String str : strs) { 13 | System.out.println(str); 14 | } 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /ch08_array_string/src/rtda/heap/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod access_flags; 2 | pub mod array_class; 3 | pub mod array_object; 4 | pub mod class; 5 | pub mod class_loader; 6 | pub mod class_name_helper; 7 | pub mod constant_pool; 8 | pub mod cp_classref; 9 | pub mod cp_fieldref; 10 | pub mod cp_methodref; 11 | pub mod cp_interface_methodref; 12 | pub mod field; 13 | pub mod method; 14 | pub mod method_descriptor; 15 | pub mod method_lookup; 16 | pub mod slots; 17 | pub mod string_pool; 18 | -------------------------------------------------------------------------------- /ch09_native/src/instructions/math/mod.rs: -------------------------------------------------------------------------------- 1 | mod add; 2 | mod sub; 3 | mod mul; 4 | mod div; 5 | mod rem; 6 | mod neg; 7 | mod and; 8 | mod or; 9 | mod xor; 10 | mod iinc; 11 | mod sh; 12 | 13 | pub use self::add::*; 14 | pub use self::sub::*; 15 | pub use self::mul::*; 16 | pub use self::div::*; 17 | pub use self::rem::*; 18 | pub use self::neg::*; 19 | pub use self::and::*; 20 | pub use self::or::*; 21 | pub use self::xor::*; 22 | pub use self::iinc::*; 23 | pub use self::sh::*; 24 | -------------------------------------------------------------------------------- /java/example/src/main/java/jvmrust/ch07/FibonacciTest.java: -------------------------------------------------------------------------------- 1 | package jvmrust.ch07; 2 | 3 | public class FibonacciTest { 4 | 5 | public static void main(String[] args) { 6 | long x = fibonacci(30); 7 | System.out.println(x); 8 | } 9 | 10 | private static long fibonacci(long n) { 11 | if (n <= 1) { 12 | return n; 13 | } else { 14 | return fibonacci(n - 1) + fibonacci(n - 2); 15 | } 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /java/example/src/main/java/jvmrust/ch09/ObjectTest.java: -------------------------------------------------------------------------------- 1 | package jvmrust.ch09; 2 | 3 | public class ObjectTest { 4 | 5 | public static void main(String[] args) { 6 | Object obj1 = new ObjectTest(); 7 | Object obj2 = new ObjectTest(); 8 | System.out.println(obj1.hashCode()); 9 | System.out.println(obj1.toString()); 10 | System.out.println(obj1.equals(obj2)); 11 | System.out.println(obj1.equals(obj1)); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /java/example/src/main/java/jvmrust/ch09/StringTest.java: -------------------------------------------------------------------------------- 1 | package jvmrust.ch09; 2 | 3 | public class StringTest { 4 | 5 | public static void main(String[] args) { 6 | String s1 = "abc1"; 7 | String s2 = "abc1"; 8 | System.out.println(s1 == s2); 9 | 10 | int x = 1; 11 | String s3 = "abc" + x; 12 | System.out.println(s1 == s3); 13 | 14 | s3 = s3.intern(); 15 | System.out.println(s1 == s3); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /ch05_instructions/src/instructions/math/mod.rs: -------------------------------------------------------------------------------- 1 | mod add; 2 | mod sub; 3 | mod mul; 4 | mod div; 5 | mod rem; 6 | mod neg; 7 | mod and; 8 | mod or; 9 | mod xor; 10 | mod iinc; 11 | mod sh; 12 | 13 | pub use self::add::*; 14 | pub use self::sub::*; 15 | pub use self::mul::*; 16 | pub use self::div::*; 17 | pub use self::rem::*; 18 | pub use self::neg::*; 19 | pub use self::and::*; 20 | pub use self::or::*; 21 | pub use self::xor::*; 22 | pub use self::iinc::*; 23 | pub use self::sh::*; 24 | -------------------------------------------------------------------------------- /ch06_rtda_heap/src/instructions/math/mod.rs: -------------------------------------------------------------------------------- 1 | mod add; 2 | mod sub; 3 | mod mul; 4 | mod div; 5 | mod rem; 6 | mod neg; 7 | mod and; 8 | mod or; 9 | mod xor; 10 | mod iinc; 11 | mod sh; 12 | 13 | pub use self::add::*; 14 | pub use self::sub::*; 15 | pub use self::mul::*; 16 | pub use self::div::*; 17 | pub use self::rem::*; 18 | pub use self::neg::*; 19 | pub use self::and::*; 20 | pub use self::or::*; 21 | pub use self::xor::*; 22 | pub use self::iinc::*; 23 | pub use self::sh::*; 24 | -------------------------------------------------------------------------------- /ch07_method_invoke/src/instructions/math/mod.rs: -------------------------------------------------------------------------------- 1 | mod add; 2 | mod sub; 3 | mod mul; 4 | mod div; 5 | mod rem; 6 | mod neg; 7 | mod and; 8 | mod or; 9 | mod xor; 10 | mod iinc; 11 | mod sh; 12 | 13 | pub use self::add::*; 14 | pub use self::sub::*; 15 | pub use self::mul::*; 16 | pub use self::div::*; 17 | pub use self::rem::*; 18 | pub use self::neg::*; 19 | pub use self::and::*; 20 | pub use self::or::*; 21 | pub use self::xor::*; 22 | pub use self::iinc::*; 23 | pub use self::sh::*; 24 | -------------------------------------------------------------------------------- /ch08_array_string/src/instructions/math/mod.rs: -------------------------------------------------------------------------------- 1 | mod add; 2 | mod sub; 3 | mod mul; 4 | mod div; 5 | mod rem; 6 | mod neg; 7 | mod and; 8 | mod or; 9 | mod xor; 10 | mod iinc; 11 | mod sh; 12 | 13 | pub use self::add::*; 14 | pub use self::sub::*; 15 | pub use self::mul::*; 16 | pub use self::div::*; 17 | pub use self::rem::*; 18 | pub use self::neg::*; 19 | pub use self::and::*; 20 | pub use self::or::*; 21 | pub use self::xor::*; 22 | pub use self::iinc::*; 23 | pub use self::sh::*; 24 | -------------------------------------------------------------------------------- /ch10_exception/src/instructions/math/mod.rs: -------------------------------------------------------------------------------- 1 | mod add; 2 | mod sub; 3 | mod mul; 4 | mod div; 5 | mod rem; 6 | mod neg; 7 | mod and; 8 | mod or; 9 | mod xor; 10 | mod iinc; 11 | mod sh; 12 | 13 | pub use self::add::*; 14 | pub use self::sub::*; 15 | pub use self::mul::*; 16 | pub use self::div::*; 17 | pub use self::rem::*; 18 | pub use self::neg::*; 19 | pub use self::and::*; 20 | pub use self::or::*; 21 | pub use self::xor::*; 22 | pub use self::iinc::*; 23 | pub use self::sh::*; 24 | -------------------------------------------------------------------------------- /ch01_cmd/src/main.rs: -------------------------------------------------------------------------------- 1 | mod cmd; 2 | 3 | use crate::cmd::{parse_cmd, Cmd}; 4 | 5 | fn main() { 6 | let cmd = parse_cmd(); 7 | 8 | if cmd.version_flag { 9 | println!("{}", "version 0.0.1"); 10 | } else if cmd.help_flag || cmd.class == "" { 11 | cmd.print_usage(); 12 | } else { 13 | start_jvm(cmd); 14 | } 15 | } 16 | 17 | fn start_jvm(cmd: Cmd) { 18 | println!("classpath: {} class: {} args: {:?}", cmd.cp_option, cmd.class, cmd.args); 19 | } 20 | -------------------------------------------------------------------------------- /ch10_exception/src/rtda/heap/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod access_flags; 2 | pub mod array_class; 3 | pub mod array_object; 4 | pub mod class; 5 | pub mod class_loader; 6 | pub mod class_name_helper; 7 | pub mod constant_pool; 8 | pub mod cp_classref; 9 | pub mod cp_fieldref; 10 | pub mod cp_methodref; 11 | pub mod cp_interface_methodref; 12 | pub mod field; 13 | pub mod method; 14 | pub mod method_descriptor; 15 | pub mod method_lookup; 16 | pub mod slots; 17 | pub mod string_pool; 18 | pub mod exception_table; 19 | -------------------------------------------------------------------------------- /java/example/src/main/java/jvmrust/ch07/Vector3D.java: -------------------------------------------------------------------------------- 1 | package jvmrust.ch07; 2 | 3 | public class Vector3D extends Vector2D { 4 | 5 | protected double z; 6 | 7 | public Vector3D() { 8 | this(1, 1, 1); 9 | } 10 | 11 | public Vector3D(double x, double y, double z) { 12 | super(x, y); 13 | this.z = z; 14 | } 15 | 16 | @Override 17 | public void multiply(double s) { 18 | super.multiply(s); 19 | this.z *= s; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /java/example/src/main/java/jvmrust/ch07/InvokeSpecialTest.java: -------------------------------------------------------------------------------- 1 | package jvmrust.ch07; 2 | 3 | public class InvokeSpecialTest { 4 | 5 | public static void main(String[] args) { 6 | Vector2D v2 = new Vector2D(2.1, 2.2); 7 | System.out.println(v2.x); 8 | System.out.println(v2.y); 9 | 10 | Vector3D v3 = new Vector3D(3.1, 3.2, 3.3); 11 | System.out.println(v3.x); 12 | System.out.println(v3.y); 13 | System.out.println(v3.z); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /java/example/src/main/java/jvmrust/ch07/Vector2D.java: -------------------------------------------------------------------------------- 1 | package jvmrust.ch07; 2 | 3 | public class Vector2D implements Vector { 4 | 5 | protected double x; 6 | protected double y; 7 | 8 | public Vector2D() { 9 | this(1, 1); 10 | } 11 | 12 | public Vector2D(double x, double y) { 13 | this.x = x; 14 | this.y = y; 15 | } 16 | 17 | @Override 18 | public void multiply(double s) { 19 | this.x *= s; 20 | this.y *= s; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /ch06_rtda_heap/src/instructions/references/mod.rs: -------------------------------------------------------------------------------- 1 | mod new; 2 | mod checkcast; 3 | mod getfield; 4 | mod getstatic; 5 | mod instanceof; 6 | mod invokespecial; 7 | mod invokevirtual; 8 | mod putfield; 9 | mod putstatic; 10 | 11 | pub use self::new::*; 12 | pub use self::checkcast::*; 13 | pub use self::getfield::*; 14 | pub use self::getstatic::*; 15 | pub use self::instanceof::*; 16 | pub use self::invokespecial::*; 17 | pub use self::invokevirtual::*; 18 | pub use self::putfield::*; 19 | pub use self::putstatic::*; 20 | -------------------------------------------------------------------------------- /java/example/src/main/java/jvmrust/ch09/HashMapTest.java: -------------------------------------------------------------------------------- 1 | package jvmrust.ch09; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | public class HashMapTest { 7 | 8 | public static void main(String[] args) { 9 | Map map = new HashMap<>(); 10 | map.put("abc", "123"); 11 | map.put("xyz", "987"); 12 | System.out.println(map.get("abc")); 13 | System.out.println(map.get("xyz")); 14 | System.out.println(map.toString()); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /java/example/src/main/java/jvmrust/ch06/FieldResolutionTest.java: -------------------------------------------------------------------------------- 1 | package jvmrust.ch06; 2 | 3 | public class FieldResolutionTest { 4 | 5 | private static interface I { 6 | static int x = 1; 7 | } 8 | 9 | private static class B { 10 | public int x; 11 | } 12 | 13 | private static class C extends B implements I { 14 | //public int x; 15 | } 16 | 17 | public static void main(String[] args) { 18 | C c = new C(); 19 | //System.out.println(c.x); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /java/example/src/main/java/jvmrust/ch07/InvokeVirtualTest.java: -------------------------------------------------------------------------------- 1 | package jvmrust.ch07; 2 | 3 | public class InvokeVirtualTest { 4 | 5 | public static void main(String[] args) { 6 | Vector2D v2 = new Vector2D(2.1, 2.2); 7 | Vector2D v3 = new Vector3D(3.1, 3.2, 3.3); 8 | v2.multiply(2); 9 | v3.multiply(3); 10 | System.out.println(v2.x); 11 | System.out.println(v2.y); 12 | System.out.println(v3.x); 13 | System.out.println(v3.y); 14 | System.out.println(((Vector3D)v3).z); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /ch08_array_string/README.md: -------------------------------------------------------------------------------- 1 | ### Chapter 8: 数组和字符串 2 | 3 | #### 编译: 4 | 5 | ```shell 6 | jvm-rust ❯ cargo build -p ch08_array_string 7 | ``` 8 | 9 | #### 运行: 10 | 11 | ```shell 12 | jvm-rust ❯ ./target/debug/ch08_array_string -cp "/Users/dxx/Desktop" jvmrust.ch08.BubbleSortTest 13 | 9 14 | 10 15 | 11 16 | 22 17 | 24 18 | 36 19 | 36 20 | 48 21 | 56 22 | 65 23 | 77 24 | 78 25 | 84 26 | 92 27 | 95 28 | 97 29 | ``` 30 | 31 | ```shell 32 | jvm-rust ❯ ./target/debug/ch08_array_string -cp "/Users/dxx/Desktop" jvmrust.ch08.PrintArgs foo 你好,世界! 33 | foo 34 | 你好,世界! 35 | ``` 36 | -------------------------------------------------------------------------------- /java/example/src/main/java/jvmrust/ch09/PrintlnTest.java: -------------------------------------------------------------------------------- 1 | package jvmrust.ch09; 2 | 3 | public class PrintlnTest { 4 | 5 | public static void main(String[] args) { 6 | System.out.println(false); 7 | System.out.println(true); 8 | System.out.println((byte)1); 9 | System.out.println((short)2); 10 | System.out.println('x'); 11 | System.out.println(3); 12 | System.out.println(4L); 13 | System.out.println(3.14f); 14 | System.out.println(3.14); 15 | System.out.println("abc"); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /ch04_rtda/src/classfile/attribute_info/attr_constant_value.rs: -------------------------------------------------------------------------------- 1 | /// ConstantValue_attribute { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u2 constantvalue_index; 5 | /// } 6 | 7 | use super::{AttributeInfo, ClassReader}; 8 | 9 | #[derive(Default)] 10 | pub struct ConstantValueAttribute { 11 | constant_value_index: u16, 12 | } 13 | 14 | impl AttributeInfo for ConstantValueAttribute { 15 | fn read_info(&mut self, reader: &mut ClassReader) { 16 | self.constant_value_index = reader.read_u16(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ch03_classfile/src/classfile/attribute_info/attr_constant_value.rs: -------------------------------------------------------------------------------- 1 | /// ConstantValue_attribute { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u2 constantvalue_index; 5 | /// } 6 | 7 | use super::{AttributeInfo, ClassReader}; 8 | 9 | #[derive(Default)] 10 | pub struct ConstantValueAttribute { 11 | constant_value_index: u16, 12 | } 13 | 14 | impl AttributeInfo for ConstantValueAttribute { 15 | fn read_info(&mut self, reader: &mut ClassReader) { 16 | self.constant_value_index = reader.read_u16(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ch09_native/src/native/java/lang/String.rs: -------------------------------------------------------------------------------- 1 | use crate::rtda::Frame; 2 | use crate::rtda::string_pool; 3 | use super::registry; 4 | 5 | const J_STRING: &str = "java/lang/String"; 6 | 7 | pub fn init() { 8 | registry(J_STRING.into(), "intern".into(), "()Ljava/lang/String;".into(), intern); 9 | } 10 | 11 | // public native String intern(); 12 | // ()Ljava/lang/String; 13 | fn intern(frame: &mut Frame) { 14 | let this = frame.local_vars_mut().get_this(); 15 | let interned = string_pool::intern_string(this.as_ref().unwrap()); 16 | 17 | frame.operand_stack_mut().push_ref(Some(interned)); 18 | } 19 | -------------------------------------------------------------------------------- /java/example/src/main/java/jvmrust/ch08/StringTest.java: -------------------------------------------------------------------------------- 1 | package jvmrust.ch08; 2 | 3 | public class StringTest { 4 | 5 | public static final String STR = "abc"; 6 | 7 | public static void main(String[] args) { 8 | String s1 = "xyz"; // ldc 9 | 10 | System.out.println(STR); 11 | System.out.println(s1); 12 | //String s2 = "abc1"; 13 | //assertSame(s1, s2); 14 | 15 | //int x = 1; 16 | //String s3 = "abc" + x; 17 | //assertNotSame(s1, s3); 18 | 19 | //s3 = s3.intern(); 20 | //assertSame(s1, s3); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /ch10_exception/src/native/java/lang/String.rs: -------------------------------------------------------------------------------- 1 | use crate::rtda::Frame; 2 | use crate::rtda::string_pool; 3 | use super::registry; 4 | 5 | const J_STRING: &str = "java/lang/String"; 6 | 7 | pub fn init() { 8 | registry(J_STRING.into(), "intern".into(), "()Ljava/lang/String;".into(), intern); 9 | } 10 | 11 | // public native String intern(); 12 | // ()Ljava/lang/String; 13 | fn intern(frame: &mut Frame) { 14 | let this = frame.local_vars_mut().get_this(); 15 | let interned = string_pool::intern_string(this.as_ref().unwrap()); 16 | 17 | frame.operand_stack_mut().push_ref(Some(interned)); 18 | } 19 | -------------------------------------------------------------------------------- /java/example/src/main/java/jvmrust/ch07/AccSuperDemo.java: -------------------------------------------------------------------------------- 1 | package jvmrust.ch07; 2 | 3 | public class AccSuperDemo { 4 | 5 | // lib1.jar 6 | public static class A { 7 | public void foo() { 8 | System.out.println("A.foo"); 9 | } 10 | } 11 | public static class B extends A { 12 | // empty 13 | } 14 | 15 | // lib2.jar 16 | public static class C extends B { 17 | public void foo() { 18 | super.foo(); 19 | } 20 | } 21 | 22 | public static void main(String[] args) { 23 | new C().foo(); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /java/example/src/main/java/jvmrust/ch08/ArrayDemo.java: -------------------------------------------------------------------------------- 1 | package jvmrust.ch08; 2 | 3 | public class ArrayDemo { 4 | 5 | public static void main(String[] args) { 6 | int[] a1 = new int[10]; // newarray 7 | String[] a2 = new String[10]; // anewarray 8 | int[][] a3 = new int[10][10]; // multianewarray 9 | int x = a1.length; // arraylength 10 | a1[0] = 100; // iastore 11 | int y = a1[0]; // iaload 12 | a2[0] = "abc"; // aastore 13 | String s = a2[0]; // aaload 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /ch04_rtda/src/classfile/attribute_info/attr_exceptions.rs: -------------------------------------------------------------------------------- 1 | /// Exceptions_attribute { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u2 number_of_exceptions; 5 | /// u2 exception_index_table[number_of_exceptions]; 6 | /// } 7 | 8 | use super::{AttributeInfo, ClassReader}; 9 | 10 | #[derive(Default)] 11 | pub struct ExceptionsAttribute { 12 | exception_index_table: Vec, 13 | } 14 | 15 | impl AttributeInfo for ExceptionsAttribute { 16 | fn read_info(&mut self, reader: &mut ClassReader) { 17 | self.exception_index_table = reader.read_u16s(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ch03_classfile/src/classfile/attribute_info/attr_exceptions.rs: -------------------------------------------------------------------------------- 1 | /// Exceptions_attribute { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u2 number_of_exceptions; 5 | /// u2 exception_index_table[number_of_exceptions]; 6 | /// } 7 | 8 | use super::{AttributeInfo, ClassReader}; 9 | 10 | #[derive(Default)] 11 | pub struct ExceptionsAttribute { 12 | exception_index_table: Vec, 13 | } 14 | 15 | impl AttributeInfo for ExceptionsAttribute { 16 | fn read_info(&mut self, reader: &mut ClassReader) { 17 | self.exception_index_table = reader.read_u16s(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ch06_rtda_heap/src/instructions/control/goto.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | use super::super::bytecode_reader::BytecodeReader; 6 | use super::super::branch; 7 | 8 | /// Branch always 9 | #[derive(Default, Debug)] 10 | pub struct GOTO { 11 | pub offset: i64, 12 | } 13 | 14 | impl Instruction for GOTO { 15 | fn fetch_operands(&mut self, reader: &mut BytecodeReader) { 16 | self.offset = reader.read_i16() as i64; 17 | } 18 | 19 | fn execute(&mut self, frame: &mut Frame) { 20 | branch(frame, self.offset); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ch07_method_invoke/src/instructions/references/mod.rs: -------------------------------------------------------------------------------- 1 | mod new; 2 | mod checkcast; 3 | mod getfield; 4 | mod getstatic; 5 | mod instanceof; 6 | mod invokeinterface; 7 | mod invokespecial; 8 | mod invokestatic; 9 | mod invokevirtual; 10 | mod putfield; 11 | mod putstatic; 12 | 13 | pub use self::new::*; 14 | pub use self::checkcast::*; 15 | pub use self::getfield::*; 16 | pub use self::getstatic::*; 17 | pub use self::instanceof::*; 18 | pub use self::invokeinterface::*; 19 | pub use self::invokespecial::*; 20 | pub use self::invokestatic::*; 21 | pub use self::invokevirtual::*; 22 | pub use self::putfield::*; 23 | pub use self::putstatic::*; 24 | -------------------------------------------------------------------------------- /ch05_instructions/src/instructions/control/goto.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | use super::super::bytecode_reader::BytecodeReader; 6 | use super::super::branch; 7 | 8 | /// Branch always 9 | #[derive(Default, Debug)] 10 | pub struct GOTO { 11 | pub offset: i64, 12 | } 13 | 14 | impl Instruction for GOTO { 15 | fn fetch_operands(&mut self, reader: &mut BytecodeReader) { 16 | self.offset = reader.read_i16() as i64; 17 | } 18 | 19 | fn execute(&mut self, frame: &mut Frame) { 20 | branch(frame, self.offset); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ch07_method_invoke/src/instructions/control/goto.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | use super::super::bytecode_reader::BytecodeReader; 6 | use super::super::branch; 7 | 8 | /// Branch always 9 | #[derive(Default, Debug)] 10 | pub struct GOTO { 11 | pub offset: i64, 12 | } 13 | 14 | impl Instruction for GOTO { 15 | fn fetch_operands(&mut self, reader: &mut BytecodeReader) { 16 | self.offset = reader.read_i16() as i64; 17 | } 18 | 19 | fn execute(&mut self, frame: &mut Frame) { 20 | branch(frame, self.offset); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ch10_exception/README.md: -------------------------------------------------------------------------------- 1 | ### Chapter 10: 异常处理 2 | 3 | #### 编译: 4 | 5 | ```shell 6 | jvm-rust ❯ cargo build -p ch10_exception 7 | ``` 8 | 9 | #### 运行: 10 | 11 | ```shell 12 | jvm-rust ❯ ./target/debug/ch10_exception -cp "/Users/dxx/Desktop" jvmrust.ch10.ArgsTest Hello World! 13 | [Hello, World!] 14 | ``` 15 | 16 | ```shell 17 | jvm-rust ❯ ./target/debug/ch10_exception -cp "/Users/dxx/Desktop" jvmrust.ch10.ArgsTest 18 | java.lang.IndexOutOfBoundsException: No args! 19 | at jvmrust.ch10.ArgsTest.bar(ArgsTest.java:21) 20 | at jvmrust.ch10.ArgsTest.foo(ArgsTest.java:13) 21 | at jvmrust.ch10.ArgsTest.main(ArgsTest.java:8) 22 | ``` 23 | -------------------------------------------------------------------------------- /java/example/src/main/java/jvmrust/ch03/ClassFileTest.java: -------------------------------------------------------------------------------- 1 | package jvmrust.ch03; 2 | 3 | public class ClassFileTest { 4 | 5 | public static final boolean FLAG = true; 6 | public static final byte BYTE = 123; 7 | public static final char X = 'X'; 8 | public static final short SHORT = 12345; 9 | public static final int INT = 123456789; 10 | public static final long LONG = 12345678901L; 11 | public static final float PI = 3.14f; 12 | public static final double E = 2.71828; 13 | 14 | public static void main(String[] args) throws RuntimeException { 15 | System.out.println("Hello, World!"); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /ch06_rtda_heap/src/instructions/extended/goto_w.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | use super::super::bytecode_reader::BytecodeReader; 6 | use super::super::branch; 7 | 8 | /// Branch always (wide index) 9 | #[derive(Default, Debug)] 10 | pub struct GOTO_W { 11 | pub offset: i64, 12 | } 13 | 14 | impl Instruction for GOTO_W { 15 | fn fetch_operands(&mut self, reader: &mut BytecodeReader) { 16 | self.offset = reader.read_i32() as i64; 17 | } 18 | 19 | fn execute(&mut self, frame: &mut Frame) { 20 | branch(frame, self.offset); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ch05_instructions/src/instructions/extended/goto_w.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | use super::super::bytecode_reader::BytecodeReader; 6 | use super::super::branch; 7 | 8 | /// Branch always (wide index) 9 | #[derive(Default, Debug)] 10 | pub struct GOTO_W { 11 | pub offset: i64, 12 | } 13 | 14 | impl Instruction for GOTO_W { 15 | fn fetch_operands(&mut self, reader: &mut BytecodeReader) { 16 | self.offset = reader.read_i32() as i64; 17 | } 18 | 19 | fn execute(&mut self, frame: &mut Frame) { 20 | branch(frame, self.offset); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ch07_method_invoke/src/instructions/extended/goto_w.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | use super::super::bytecode_reader::BytecodeReader; 6 | use super::super::branch; 7 | 8 | /// Branch always (wide index) 9 | #[derive(Default, Debug)] 10 | pub struct GOTO_W { 11 | pub offset: i64, 12 | } 13 | 14 | impl Instruction for GOTO_W { 15 | fn fetch_operands(&mut self, reader: &mut BytecodeReader) { 16 | self.offset = reader.read_i32() as i64; 17 | } 18 | 19 | fn execute(&mut self, frame: &mut Frame) { 20 | branch(frame, self.offset); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /java/example/src/main/java/jvmrust/ch10/ExceptionTest2.java: -------------------------------------------------------------------------------- 1 | package jvmrust.ch10; 2 | 3 | public class ExceptionTest2 { 4 | 5 | public static void main(String[] args) { 6 | safe(0); 7 | safe(1); 8 | } 9 | 10 | private static void safe(int x) { 11 | try { 12 | dangerous(x); 13 | System.out.println(x); 14 | } catch (IllegalArgumentException e) { 15 | System.out.println(e.getMessage()); 16 | } 17 | } 18 | 19 | private static void dangerous(int x) { 20 | if (x == 0) { 21 | throw new IllegalArgumentException("0!"); 22 | } 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jvm-rust 2 | 3 | 参考[自己动手写 Java 虚拟机](https://github.com/zxh0/jvmgo-book)源码,用 Rust 语言实现 JVM。 4 | 5 | ## 开发环境 6 | 7 | * MacOS Monterey 12.1 8 | * Rust 1.57.0 9 | * JDK 1.8 10 | 11 | ## 目录说明 12 | 13 | 本源码目录结构按照 [jvmgo-book](https://github.com/zxh0/jvmgo-book) 组织,说明如下: 14 | 15 | * ch01_cmd: 命令行处理 16 | * ch02_classpath: 查找 Class 文件 17 | * ch03_classfile: 解析 Class 文件 18 | * ch04_rtda: 运行时数据区 19 | * ch05_instructions: 指令集和解释器 20 | * ch06_rtda_heap: 类和对象 21 | * ch07_method_invoke: 方法调用和返回 22 | * ch08_array_string: 数组和字符串 23 | * ch09_native: 本地方法调用 24 | * ch10_exception: 异常处理 25 | 26 | `java` 目录存放测试使用的 Java 代码。 27 | 28 | ## 运行 29 | 30 | 参考每个目录中的 `README.md`。 31 | -------------------------------------------------------------------------------- /ch05_instructions/src/classfile/attribute_info/attr_constant_value.rs: -------------------------------------------------------------------------------- 1 | /// ConstantValue_attribute { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u2 constantvalue_index; 5 | /// } 6 | 7 | use super::{AttributeInfo, ClassReader}; 8 | 9 | #[derive(Default)] 10 | pub struct ConstantValueAttribute { 11 | constant_value_index: u16, 12 | } 13 | 14 | impl AttributeInfo for ConstantValueAttribute { 15 | fn read_info(&mut self, reader: &mut ClassReader) { 16 | self.constant_value_index = reader.read_u16(); 17 | } 18 | 19 | fn as_any(&self) -> &dyn std::any::Any { 20 | self 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ch06_rtda_heap/src/instructions/comparisons/lcmp.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | /// Compare long 7 | #[derive(Default, Debug)] 8 | pub struct LCMP; 9 | 10 | impl Instruction for LCMP { 11 | fn execute(&mut self, frame: &mut Frame) { 12 | let stack = frame.operand_stack_mut(); 13 | let v2 = stack.pop_long(); 14 | let v1 = stack.pop_long(); 15 | if v1 > v2 { 16 | stack.push_int(1); 17 | } else if v1 == v2 { 18 | stack.push_int(0); 19 | } else { 20 | stack.push_int(-1); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ch05_instructions/src/instructions/comparisons/lcmp.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | /// Compare long 7 | #[derive(Default, Debug)] 8 | pub struct LCMP; 9 | 10 | impl Instruction for LCMP { 11 | fn execute(&mut self, frame: &mut Frame) { 12 | let stack = frame.operand_stack_mut(); 13 | let v2 = stack.pop_long(); 14 | let v1 = stack.pop_long(); 15 | if v1 > v2 { 16 | stack.push_int(1); 17 | } else if v1 == v2 { 18 | stack.push_int(0); 19 | } else { 20 | stack.push_int(-1); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ch07_method_invoke/src/instructions/comparisons/lcmp.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | /// Compare long 7 | #[derive(Default, Debug)] 8 | pub struct LCMP; 9 | 10 | impl Instruction for LCMP { 11 | fn execute(&mut self, frame: &mut Frame) { 12 | let stack = frame.operand_stack_mut(); 13 | let v2 = stack.pop_long(); 14 | let v1 = stack.pop_long(); 15 | if v1 > v2 { 16 | stack.push_int(1); 17 | } else if v1 == v2 { 18 | stack.push_int(0); 19 | } else { 20 | stack.push_int(-1); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ch09_native/src/instructions/control/goto.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | use super::super::bytecode_reader::BytecodeReader; 6 | use super::super::branch; 7 | 8 | /// Branch always 9 | #[derive(Default, Debug)] 10 | pub struct GOTO { 11 | pub offset: i64, 12 | } 13 | 14 | impl Instruction for GOTO { 15 | fn fetch_operands(&mut self, reader: &mut BytecodeReader) { 16 | self.offset = reader.read_i16() as i64; 17 | } 18 | 19 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 20 | branch(frame, self.offset); 21 | 22 | Ok(()) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ch10_exception/src/instructions/control/goto.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | use super::super::bytecode_reader::BytecodeReader; 6 | use super::super::branch; 7 | 8 | /// Branch always 9 | #[derive(Default, Debug)] 10 | pub struct GOTO { 11 | pub offset: i64, 12 | } 13 | 14 | impl Instruction for GOTO { 15 | fn fetch_operands(&mut self, reader: &mut BytecodeReader) { 16 | self.offset = reader.read_i16() as i64; 17 | } 18 | 19 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 20 | branch(frame, self.offset); 21 | 22 | Ok(()) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ch08_array_string/src/instructions/control/goto.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | use super::super::bytecode_reader::BytecodeReader; 6 | use super::super::branch; 7 | 8 | /// Branch always 9 | #[derive(Default, Debug)] 10 | pub struct GOTO { 11 | pub offset: i64, 12 | } 13 | 14 | impl Instruction for GOTO { 15 | fn fetch_operands(&mut self, reader: &mut BytecodeReader) { 16 | self.offset = reader.read_i16() as i64; 17 | } 18 | 19 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 20 | branch(frame, self.offset); 21 | 22 | Ok(()) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ch04_rtda/src/rtda/frame.rs: -------------------------------------------------------------------------------- 1 | use super::{local_vars::LocalVars, operand_stack::OperandStack}; 2 | 3 | /// Stack Frame 4 | pub struct Frame { 5 | local_vars: LocalVars, 6 | operand_stack: OperandStack, 7 | } 8 | 9 | impl Frame { 10 | pub fn new(max_locals: usize, max_size: usize) -> Self { 11 | Frame { 12 | local_vars: LocalVars::new(max_locals), 13 | operand_stack: OperandStack::new(max_size), 14 | } 15 | } 16 | 17 | pub fn local_vars_mut(&mut self) -> &mut LocalVars { 18 | &mut self.local_vars 19 | } 20 | 21 | pub fn operand_stack_mut(&mut self) -> &mut OperandStack { 22 | &mut self.operand_stack 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ch09_native/src/instructions/extended/goto_w.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | use super::super::bytecode_reader::BytecodeReader; 6 | use super::super::branch; 7 | 8 | /// Branch always (wide index) 9 | #[derive(Default, Debug)] 10 | pub struct GOTO_W { 11 | pub offset: i64, 12 | } 13 | 14 | impl Instruction for GOTO_W { 15 | fn fetch_operands(&mut self, reader: &mut BytecodeReader) { 16 | self.offset = reader.read_i32() as i64; 17 | } 18 | 19 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 20 | branch(frame, self.offset); 21 | 22 | Ok(()) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ch10_exception/src/instructions/extended/goto_w.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | use super::super::bytecode_reader::BytecodeReader; 6 | use super::super::branch; 7 | 8 | /// Branch always (wide index) 9 | #[derive(Default, Debug)] 10 | pub struct GOTO_W { 11 | pub offset: i64, 12 | } 13 | 14 | impl Instruction for GOTO_W { 15 | fn fetch_operands(&mut self, reader: &mut BytecodeReader) { 16 | self.offset = reader.read_i32() as i64; 17 | } 18 | 19 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 20 | branch(frame, self.offset); 21 | 22 | Ok(()) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /java/example/src/main/java/jvmrust/ch10/ArgsTest.java: -------------------------------------------------------------------------------- 1 | package jvmrust.ch10; 2 | 3 | import java.util.Arrays; 4 | 5 | public class ArgsTest { 6 | 7 | public static void main(String[] args) { 8 | foo(args); 9 | } 10 | 11 | private static void foo(String[] args) { 12 | try { 13 | bar(args); 14 | } catch (NumberFormatException e) { 15 | System.out.println(e.getMessage()); 16 | } 17 | } 18 | 19 | private static void bar(String[] args) { 20 | if (args.length == 0) { 21 | throw new IndexOutOfBoundsException("No args!"); 22 | } 23 | System.out.println(Arrays.toString(args)); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /ch08_array_string/src/instructions/extended/goto_w.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | use super::super::bytecode_reader::BytecodeReader; 6 | use super::super::branch; 7 | 8 | /// Branch always (wide index) 9 | #[derive(Default, Debug)] 10 | pub struct GOTO_W { 11 | pub offset: i64, 12 | } 13 | 14 | impl Instruction for GOTO_W { 15 | fn fetch_operands(&mut self, reader: &mut BytecodeReader) { 16 | self.offset = reader.read_i32() as i64; 17 | } 18 | 19 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 20 | branch(frame, self.offset); 21 | 22 | Ok(()) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ch09_native/src/classfile/attribute_info/attr_exceptions.rs: -------------------------------------------------------------------------------- 1 | /// Exceptions_attribute { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u2 number_of_exceptions; 5 | /// u2 exception_index_table[number_of_exceptions]; 6 | /// } 7 | 8 | use super::{AttributeInfo, ClassReader}; 9 | 10 | #[derive(Default)] 11 | pub struct ExceptionsAttribute { 12 | exception_index_table: Vec, 13 | } 14 | 15 | impl AttributeInfo for ExceptionsAttribute { 16 | fn read_info(&mut self, reader: &mut ClassReader) { 17 | self.exception_index_table = reader.read_u16s(); 18 | } 19 | 20 | fn as_any(&self) -> &dyn std::any::Any { 21 | self 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ch10_exception/src/classfile/attribute_info/attr_exceptions.rs: -------------------------------------------------------------------------------- 1 | /// Exceptions_attribute { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u2 number_of_exceptions; 5 | /// u2 exception_index_table[number_of_exceptions]; 6 | /// } 7 | 8 | use super::{AttributeInfo, ClassReader}; 9 | 10 | #[derive(Default)] 11 | pub struct ExceptionsAttribute { 12 | exception_index_table: Vec, 13 | } 14 | 15 | impl AttributeInfo for ExceptionsAttribute { 16 | fn read_info(&mut self, reader: &mut ClassReader) { 17 | self.exception_index_table = reader.read_u16s(); 18 | } 19 | 20 | fn as_any(&self) -> &dyn std::any::Any { 21 | self 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ch04_rtda/src/classfile/constant_pool/cp_name_and_type.rs: -------------------------------------------------------------------------------- 1 | /// CONSTANT_NameAndType_info { 2 | /// u1 tag; 3 | /// u2 name_index; 4 | /// u2 descriptor_index; 5 | /// } 6 | 7 | use super::{ConstantInfo, ClassReader}; 8 | 9 | #[derive(Default)] 10 | pub struct ConstantNameAndTypeInfo { 11 | name_index: u16, 12 | descriptor_index: u16, 13 | } 14 | 15 | impl ConstantInfo for ConstantNameAndTypeInfo { 16 | fn read_info(&mut self, reader: &mut ClassReader) { 17 | self.name_index = reader.read_u16(); 18 | self.descriptor_index = reader.read_u16(); 19 | } 20 | 21 | fn tag(&self) -> u8 { 22 | super::CONSTANT_NAME_AND_TYPE 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ch07_method_invoke/src/classfile/attribute_info/attr_exceptions.rs: -------------------------------------------------------------------------------- 1 | /// Exceptions_attribute { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u2 number_of_exceptions; 5 | /// u2 exception_index_table[number_of_exceptions]; 6 | /// } 7 | 8 | use super::{AttributeInfo, ClassReader}; 9 | 10 | #[derive(Default)] 11 | pub struct ExceptionsAttribute { 12 | exception_index_table: Vec, 13 | } 14 | 15 | impl AttributeInfo for ExceptionsAttribute { 16 | fn read_info(&mut self, reader: &mut ClassReader) { 17 | self.exception_index_table = reader.read_u16s(); 18 | } 19 | 20 | fn as_any(&self) -> &dyn std::any::Any { 21 | self 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ch08_array_string/src/classfile/attribute_info/attr_exceptions.rs: -------------------------------------------------------------------------------- 1 | /// Exceptions_attribute { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u2 number_of_exceptions; 5 | /// u2 exception_index_table[number_of_exceptions]; 6 | /// } 7 | 8 | use super::{AttributeInfo, ClassReader}; 9 | 10 | #[derive(Default)] 11 | pub struct ExceptionsAttribute { 12 | exception_index_table: Vec, 13 | } 14 | 15 | impl AttributeInfo for ExceptionsAttribute { 16 | fn read_info(&mut self, reader: &mut ClassReader) { 17 | self.exception_index_table = reader.read_u16s(); 18 | } 19 | 20 | fn as_any(&self) -> &dyn std::any::Any { 21 | self 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ch03_classfile/src/classfile/constant_pool/cp_name_and_type.rs: -------------------------------------------------------------------------------- 1 | /// CONSTANT_NameAndType_info { 2 | /// u1 tag; 3 | /// u2 name_index; 4 | /// u2 descriptor_index; 5 | /// } 6 | 7 | use super::{ConstantInfo, ClassReader}; 8 | 9 | #[derive(Default)] 10 | pub struct ConstantNameAndTypeInfo { 11 | name_index: u16, 12 | descriptor_index: u16, 13 | } 14 | 15 | impl ConstantInfo for ConstantNameAndTypeInfo { 16 | fn read_info(&mut self, reader: &mut ClassReader) { 17 | self.name_index = reader.read_u16(); 18 | self.descriptor_index = reader.read_u16(); 19 | } 20 | 21 | fn tag(&self) -> u8 { 22 | super::CONSTANT_NAME_AND_TYPE 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ch05_instructions/src/classfile/constant_pool/cp_name_and_type.rs: -------------------------------------------------------------------------------- 1 | /// CONSTANT_NameAndType_info { 2 | /// u1 tag; 3 | /// u2 name_index; 4 | /// u2 descriptor_index; 5 | /// } 6 | 7 | use super::{ConstantInfo, ClassReader}; 8 | 9 | #[derive(Default)] 10 | pub struct ConstantNameAndTypeInfo { 11 | name_index: u16, 12 | descriptor_index: u16, 13 | } 14 | 15 | impl ConstantInfo for ConstantNameAndTypeInfo { 16 | fn read_info(&mut self, reader: &mut ClassReader) { 17 | self.name_index = reader.read_u16(); 18 | self.descriptor_index = reader.read_u16(); 19 | } 20 | 21 | fn tag(&self) -> u8 { 22 | super::CONSTANT_NAME_AND_TYPE 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ch09_native/src/instructions/comparisons/lcmp.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | /// Compare long 7 | #[derive(Default, Debug)] 8 | pub struct LCMP; 9 | 10 | impl Instruction for LCMP { 11 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 12 | let stack = frame.operand_stack_mut(); 13 | let v2 = stack.pop_long(); 14 | let v1 = stack.pop_long(); 15 | if v1 > v2 { 16 | stack.push_int(1); 17 | } else if v1 == v2 { 18 | stack.push_int(0); 19 | } else { 20 | stack.push_int(-1); 21 | } 22 | 23 | Ok(()) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /ch10_exception/src/instructions/comparisons/lcmp.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | /// Compare long 7 | #[derive(Default, Debug)] 8 | pub struct LCMP; 9 | 10 | impl Instruction for LCMP { 11 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 12 | let stack = frame.operand_stack_mut(); 13 | let v2 = stack.pop_long(); 14 | let v1 = stack.pop_long(); 15 | if v1 > v2 { 16 | stack.push_int(1); 17 | } else if v1 == v2 { 18 | stack.push_int(0); 19 | } else { 20 | stack.push_int(-1); 21 | } 22 | 23 | Ok(()) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /ch08_array_string/src/instructions/comparisons/lcmp.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | /// Compare long 7 | #[derive(Default, Debug)] 8 | pub struct LCMP; 9 | 10 | impl Instruction for LCMP { 11 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 12 | let stack = frame.operand_stack_mut(); 13 | let v2 = stack.pop_long(); 14 | let v1 = stack.pop_long(); 15 | if v1 > v2 { 16 | stack.push_int(1); 17 | } else if v1 == v2 { 18 | stack.push_int(0); 19 | } else { 20 | stack.push_int(-1); 21 | } 22 | 23 | Ok(()) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /ch09_native/src/instructions/references/arraylength.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | /// Get length of array 7 | #[derive(Default, Debug)] 8 | pub struct ARRAY_LENGTH; 9 | 10 | impl Instruction for ARRAY_LENGTH { 11 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 12 | let stack = frame.operand_stack_mut(); 13 | let _ref = stack.pop_ref(); 14 | if _ref.is_none() { 15 | panic!("java.lang.NullPointerException"); 16 | } 17 | 18 | let arr_len = _ref.unwrap().borrow().array_length(); 19 | stack.push_int(arr_len as i32); 20 | 21 | Ok(()) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ch05_instructions/src/classfile/attribute_info/attr_exceptions.rs: -------------------------------------------------------------------------------- 1 | /// Exceptions_attribute { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u2 number_of_exceptions; 5 | /// u2 exception_index_table[number_of_exceptions]; 6 | /// } 7 | 8 | use super::{AttributeInfo, ClassReader}; 9 | 10 | #[derive(Default)] 11 | pub struct ExceptionsAttribute { 12 | exception_index_table: Vec, 13 | } 14 | 15 | impl AttributeInfo for ExceptionsAttribute { 16 | fn read_info(&mut self, reader: &mut ClassReader) { 17 | self.exception_index_table = reader.read_u16s(); 18 | } 19 | 20 | fn as_any(&self) -> &dyn std::any::Any { 21 | self 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ch06_rtda_heap/src/classfile/attribute_info/attr_exceptions.rs: -------------------------------------------------------------------------------- 1 | /// Exceptions_attribute { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u2 number_of_exceptions; 5 | /// u2 exception_index_table[number_of_exceptions]; 6 | /// } 7 | 8 | use super::{AttributeInfo, ClassReader}; 9 | 10 | #[derive(Default)] 11 | pub struct ExceptionsAttribute { 12 | exception_index_table: Vec, 13 | } 14 | 15 | impl AttributeInfo for ExceptionsAttribute { 16 | fn read_info(&mut self, reader: &mut ClassReader) { 17 | self.exception_index_table = reader.read_u16s(); 18 | } 19 | 20 | fn as_any(&self) -> &dyn std::any::Any { 21 | self 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ch06_rtda_heap/src/instructions/stack/swap.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | /// Swap the top two operand stack values 7 | #[derive(Default, Debug)] 8 | pub struct SWAP; 9 | 10 | impl Instruction for SWAP { 11 | /// bottom -> top 12 | /// [...][c][b][a] 13 | /// \/ 14 | /// /\ 15 | /// V V 16 | /// [...][c][a][b] 17 | fn execute(&mut self, frame: &mut Frame) { 18 | let stack = frame.operand_stack_mut(); 19 | let slot1 = stack.pop_slot(); 20 | let slot2 = stack .pop_slot(); 21 | stack.push_slot(slot1); 22 | stack.push_slot(slot2); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ch10_exception/src/instructions/references/arraylength.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | /// Get length of array 7 | #[derive(Default, Debug)] 8 | pub struct ARRAY_LENGTH; 9 | 10 | impl Instruction for ARRAY_LENGTH { 11 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 12 | let stack = frame.operand_stack_mut(); 13 | let _ref = stack.pop_ref(); 14 | if _ref.is_none() { 15 | panic!("java.lang.NullPointerException"); 16 | } 17 | 18 | let arr_len = _ref.unwrap().borrow().array_length(); 19 | stack.push_int(arr_len as i32); 20 | 21 | Ok(()) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ch05_instructions/src/instructions/stack/swap.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | /// Swap the top two operand stack values 7 | #[derive(Default, Debug)] 8 | pub struct SWAP; 9 | 10 | impl Instruction for SWAP { 11 | /// bottom -> top 12 | /// [...][c][b][a] 13 | /// \/ 14 | /// /\ 15 | /// V V 16 | /// [...][c][a][b] 17 | fn execute(&mut self, frame: &mut Frame) { 18 | let stack = frame.operand_stack_mut(); 19 | let slot1 = stack.pop_slot(); 20 | let slot2 = stack .pop_slot(); 21 | stack.push_slot(slot1); 22 | stack.push_slot(slot2); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ch07_method_invoke/src/instructions/stack/swap.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | /// Swap the top two operand stack values 7 | #[derive(Default, Debug)] 8 | pub struct SWAP; 9 | 10 | impl Instruction for SWAP { 11 | /// bottom -> top 12 | /// [...][c][b][a] 13 | /// \/ 14 | /// /\ 15 | /// V V 16 | /// [...][c][a][b] 17 | fn execute(&mut self, frame: &mut Frame) { 18 | let stack = frame.operand_stack_mut(); 19 | let slot1 = stack.pop_slot(); 20 | let slot2 = stack .pop_slot(); 21 | stack.push_slot(slot1); 22 | stack.push_slot(slot2); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ch08_array_string/src/instructions/references/arraylength.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | /// Get length of array 7 | #[derive(Default, Debug)] 8 | pub struct ARRAY_LENGTH; 9 | 10 | impl Instruction for ARRAY_LENGTH { 11 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 12 | let stack = frame.operand_stack_mut(); 13 | let _ref = stack.pop_ref(); 14 | if _ref.is_none() { 15 | panic!("java.lang.NullPointerException"); 16 | } 17 | 18 | let arr_len = _ref.unwrap().borrow().array_length(); 19 | stack.push_int(arr_len as i32); 20 | 21 | Ok(()) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /java/example/src/main/java/jvmrust/ch08/Array3D.java: -------------------------------------------------------------------------------- 1 | package jvmrust.ch08; 2 | 3 | public class Array3D { 4 | 5 | public static void main(String[] args) { 6 | int[][][] threeD = new int[5][4][3]; 7 | 8 | for (int i = 0; i < 5; ++i) { 9 | for (int j = 0; j < 4; ++j) { 10 | for (int k = 0; k < 3; ++k) { 11 | threeD[i][j][k] = i + j + k; 12 | } 13 | } 14 | } 15 | 16 | for (int i = 0; i < 5; ++i) { 17 | for (int j = 0; j < 4; ++j) { 18 | for (int k = 0; k < 3; ++k) { 19 | System.out.println(threeD[i][j][k]); 20 | } 21 | } 22 | } 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /java/example/src/main/java/jvmrust/ch06/MyObject.java: -------------------------------------------------------------------------------- 1 | package jvmrust.ch06; 2 | 3 | public class MyObject { 4 | 5 | public static int staticVar; 6 | public int instanceVar; 7 | 8 | public static void main(String[] args) { 9 | int x = 32768; // ldc 10 | MyObject myObj = new MyObject(); // new 11 | MyObject.staticVar = x; // putstatic 12 | x = MyObject.staticVar; // getstatic 13 | myObj.instanceVar = x; // putfield 14 | x = myObj.instanceVar; // getfield 15 | Object obj = myObj; 16 | if (obj instanceof MyObject) { // instanceof 17 | myObj = (MyObject) obj; // checkcast 18 | System.out.println(myObj.instanceVar); 19 | } 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /ch06_rtda_heap/src/instructions/references/invokespecial.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | use super::super::bytecode_reader::BytecodeReader; 6 | 7 | /// Invoke instance method; 8 | /// Special handling for superclass, private, and instance initialization method invocations 9 | #[derive(Default, Debug)] 10 | pub struct INVOKE_SPECIAL { 11 | index: u64, 12 | } 13 | 14 | impl Instruction for INVOKE_SPECIAL { 15 | fn fetch_operands(&mut self, reader: &mut BytecodeReader) { 16 | self.index = reader.read_u16() as u64; 17 | } 18 | 19 | /// Hack! 20 | fn execute(&mut self, frame: &mut Frame) { 21 | frame.operand_stack_mut().pop_ref(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ch09_native/src/instructions/stack/swap.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | /// Swap the top two operand stack values 7 | #[derive(Default, Debug)] 8 | pub struct SWAP; 9 | 10 | impl Instruction for SWAP { 11 | /// bottom -> top 12 | /// [...][c][b][a] 13 | /// \/ 14 | /// /\ 15 | /// V V 16 | /// [...][c][a][b] 17 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 18 | let stack = frame.operand_stack_mut(); 19 | let slot1 = stack.pop_slot(); 20 | let slot2 = stack .pop_slot(); 21 | stack.push_slot(slot1); 22 | stack.push_slot(slot2); 23 | 24 | Ok(()) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ch08_array_string/src/instructions/stack/swap.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | /// Swap the top two operand stack values 7 | #[derive(Default, Debug)] 8 | pub struct SWAP; 9 | 10 | impl Instruction for SWAP { 11 | /// bottom -> top 12 | /// [...][c][b][a] 13 | /// \/ 14 | /// /\ 15 | /// V V 16 | /// [...][c][a][b] 17 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 18 | let stack = frame.operand_stack_mut(); 19 | let slot1 = stack.pop_slot(); 20 | let slot2 = stack .pop_slot(); 21 | stack.push_slot(slot1); 22 | stack.push_slot(slot2); 23 | 24 | Ok(()) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ch10_exception/src/instructions/stack/swap.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | /// Swap the top two operand stack values 7 | #[derive(Default, Debug)] 8 | pub struct SWAP; 9 | 10 | impl Instruction for SWAP { 11 | /// bottom -> top 12 | /// [...][c][b][a] 13 | /// \/ 14 | /// /\ 15 | /// V V 16 | /// [...][c][a][b] 17 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 18 | let stack = frame.operand_stack_mut(); 19 | let slot1 = stack.pop_slot(); 20 | let slot2 = stack .pop_slot(); 21 | stack.push_slot(slot1); 22 | stack.push_slot(slot2); 23 | 24 | Ok(()) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /java/example/src/main/java/jvmrust/ch07/InvokeDemo.java: -------------------------------------------------------------------------------- 1 | package jvmrust.ch07; 2 | 3 | public class InvokeDemo implements Runnable { 4 | 5 | public static void main(String[] args) { 6 | new InvokeDemo().test(); 7 | } 8 | 9 | public void test() { 10 | InvokeDemo.staticMethod(); // invokestatic 11 | InvokeDemo demo = new InvokeDemo(); // invokespecial 12 | demo.instanceMethod(); // invokespecial 13 | super.equals(null); // invokespecial 14 | this.run(); // invokevirtual 15 | ((Runnable) demo).run(); // invokeinterface 16 | } 17 | 18 | public static void staticMethod() {} 19 | private void instanceMethod() {} 20 | @Override public void run() {} 21 | 22 | } 23 | -------------------------------------------------------------------------------- /ch04_rtda/src/rtda/thread.rs: -------------------------------------------------------------------------------- 1 | use crate::types::{ 2 | RcRefCell, 3 | OptionalRcRefCell, 4 | }; 5 | use super::jvm_stack::Stack; 6 | use super::frame::Frame; 7 | 8 | pub struct Thread { 9 | pc: i64, 10 | stack: Stack, 11 | } 12 | 13 | impl Thread { 14 | pub fn new() -> Self { 15 | Thread { pc: 0, stack: Stack::new(1024) } 16 | } 17 | 18 | pub fn pc(&self) -> i64 { 19 | self.pc 20 | } 21 | 22 | pub fn set_pc(&mut self, pc: i64) { 23 | self.pc = pc; 24 | } 25 | 26 | pub fn push_frame(&mut self, frame: Frame) { 27 | self.stack.push(frame); 28 | } 29 | 30 | pub fn pop_frame(&mut self) -> OptionalRcRefCell { 31 | self.stack.pop() 32 | } 33 | 34 | pub fn current_frame(&self) -> RcRefCell { 35 | self.stack.top() 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /ch09_native/src/instructions/references/mod.rs: -------------------------------------------------------------------------------- 1 | mod anewarray; 2 | mod arraylength; 3 | mod multianewarray; 4 | mod new; 5 | mod newarray; 6 | mod checkcast; 7 | mod getfield; 8 | mod getstatic; 9 | mod instanceof; 10 | mod invokeinterface; 11 | mod invokespecial; 12 | mod invokestatic; 13 | mod invokevirtual; 14 | mod putfield; 15 | mod putstatic; 16 | 17 | pub use self::anewarray::*; 18 | pub use self::arraylength::*; 19 | pub use self::multianewarray::*; 20 | pub use self::new::*; 21 | pub use self::newarray::*; 22 | pub use self::checkcast::*; 23 | pub use self::getfield::*; 24 | pub use self::getstatic::*; 25 | pub use self::instanceof::*; 26 | pub use self::invokeinterface::*; 27 | pub use self::invokespecial::*; 28 | pub use self::invokestatic::*; 29 | pub use self::invokevirtual::*; 30 | pub use self::putfield::*; 31 | pub use self::putstatic::*; 32 | -------------------------------------------------------------------------------- /ch08_array_string/src/instructions/references/mod.rs: -------------------------------------------------------------------------------- 1 | mod anewarray; 2 | mod arraylength; 3 | mod multianewarray; 4 | mod new; 5 | mod newarray; 6 | mod checkcast; 7 | mod getfield; 8 | mod getstatic; 9 | mod instanceof; 10 | mod invokeinterface; 11 | mod invokespecial; 12 | mod invokestatic; 13 | mod invokevirtual; 14 | mod putfield; 15 | mod putstatic; 16 | 17 | pub use self::anewarray::*; 18 | pub use self::arraylength::*; 19 | pub use self::multianewarray::*; 20 | pub use self::new::*; 21 | pub use self::newarray::*; 22 | pub use self::checkcast::*; 23 | pub use self::getfield::*; 24 | pub use self::getstatic::*; 25 | pub use self::instanceof::*; 26 | pub use self::invokeinterface::*; 27 | pub use self::invokespecial::*; 28 | pub use self::invokestatic::*; 29 | pub use self::invokevirtual::*; 30 | pub use self::putfield::*; 31 | pub use self::putstatic::*; 32 | -------------------------------------------------------------------------------- /ch05_instructions/src/instructions/math/iinc.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | use super::super::bytecode_reader::BytecodeReader; 6 | 7 | /// Increment local variable by constant 8 | #[derive(Default, Debug)] 9 | pub struct IINC { 10 | pub index: usize, 11 | pub _const: i32, 12 | } 13 | 14 | impl Instruction for IINC { 15 | fn fetch_operands(&mut self, reader: &mut BytecodeReader) { 16 | self.index = reader.read_u8() as usize; 17 | self._const = reader.read_i8() as i32; 18 | } 19 | 20 | fn execute(&mut self, frame: &mut Frame) { 21 | let local_vars = frame.local_vars_mut(); 22 | let val = local_vars.get_int(self.index); 23 | let val = val + self._const; 24 | local_vars.set_int(self.index, val); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ch06_rtda_heap/src/instructions/math/iinc.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | use super::super::bytecode_reader::BytecodeReader; 6 | 7 | /// Increment local variable by constant 8 | #[derive(Default, Debug)] 9 | pub struct IINC { 10 | pub index: usize, 11 | pub _const: i32, 12 | } 13 | 14 | impl Instruction for IINC { 15 | fn fetch_operands(&mut self, reader: &mut BytecodeReader) { 16 | self.index = reader.read_u8() as usize; 17 | self._const = reader.read_i8() as i32; 18 | } 19 | 20 | fn execute(&mut self, frame: &mut Frame) { 21 | let local_vars = frame.local_vars_mut(); 22 | let val = local_vars.get_int(self.index); 23 | let val = val + self._const; 24 | local_vars.set_int(self.index, val); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ch07_method_invoke/src/instructions/math/iinc.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | use super::super::bytecode_reader::BytecodeReader; 6 | 7 | /// Increment local variable by constant 8 | #[derive(Default, Debug)] 9 | pub struct IINC { 10 | pub index: usize, 11 | pub _const: i32, 12 | } 13 | 14 | impl Instruction for IINC { 15 | fn fetch_operands(&mut self, reader: &mut BytecodeReader) { 16 | self.index = reader.read_u8() as usize; 17 | self._const = reader.read_i8() as i32; 18 | } 19 | 20 | fn execute(&mut self, frame: &mut Frame) { 21 | let local_vars = frame.local_vars_mut(); 22 | let val = local_vars.get_int(self.index); 23 | let val = val + self._const; 24 | local_vars.set_int(self.index, val); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ch04_rtda/src/classfile/attribute_info/attr_signature.rs: -------------------------------------------------------------------------------- 1 | /// Signature_attribute { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u2 signature_index; 5 | /// } 6 | 7 | use crate::types::RcRefCell; 8 | use super::ConstantPool; 9 | use super::{AttributeInfo, ClassReader}; 10 | 11 | #[derive(Default)] 12 | pub struct SignatureAttribute { 13 | constant_pool: RcRefCell, 14 | signature_index: u16, 15 | } 16 | 17 | impl AttributeInfo for SignatureAttribute { 18 | fn read_info(&mut self, reader: &mut ClassReader) { 19 | self.signature_index = reader.read_u16(); 20 | } 21 | } 22 | 23 | impl SignatureAttribute { 24 | pub fn new (cp: RcRefCell) -> Self { 25 | let mut sa = SignatureAttribute::default(); 26 | sa.constant_pool = cp; 27 | sa 28 | } 29 | } -------------------------------------------------------------------------------- /ch04_rtda/src/classfile/constant_pool/cp_string.rs: -------------------------------------------------------------------------------- 1 | /// CONSTANT_String_info { 2 | /// u1 tag; 3 | /// u2 string_index; 4 | /// } 5 | 6 | use crate::types::RcRefCell; 7 | use super::{ConstantInfo, ClassReader, ConstantPool}; 8 | 9 | pub struct ConstantStringInfo { 10 | constant_pool: RcRefCell, 11 | string_index: u16 12 | } 13 | 14 | impl ConstantInfo for ConstantStringInfo { 15 | fn read_info(&mut self, reader: &mut ClassReader) { 16 | self.string_index = reader.read_u16(); 17 | } 18 | 19 | fn tag(&self) -> u8 { 20 | super::CONSTANT_STRING 21 | } 22 | 23 | } 24 | 25 | impl ConstantStringInfo { 26 | pub fn new(cp: RcRefCell) -> Self { 27 | ConstantStringInfo { 28 | constant_pool: cp, 29 | string_index: 0, 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ch09_native/src/classfile/attribute_info/attr_constant_value.rs: -------------------------------------------------------------------------------- 1 | /// ConstantValue_attribute { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u2 constantvalue_index; 5 | /// } 6 | 7 | use super::{AttributeInfo, ClassReader}; 8 | 9 | #[derive(Default)] 10 | pub struct ConstantValueAttribute { 11 | constant_value_index: u16, 12 | } 13 | 14 | impl AttributeInfo for ConstantValueAttribute { 15 | fn read_info(&mut self, reader: &mut ClassReader) { 16 | self.constant_value_index = reader.read_u16(); 17 | } 18 | 19 | fn name(&self) -> &str { 20 | return "ConstantValue"; 21 | } 22 | 23 | fn as_any(&self) -> &dyn std::any::Any { 24 | self 25 | } 26 | } 27 | 28 | impl ConstantValueAttribute { 29 | pub fn constant_value_index(&self) -> u16 { 30 | self.constant_value_index 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ch03_classfile/src/classfile/attribute_info/attr_signature.rs: -------------------------------------------------------------------------------- 1 | /// Signature_attribute { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u2 signature_index; 5 | /// } 6 | 7 | use crate::types::RcRefCell; 8 | use super::ConstantPool; 9 | use super::{AttributeInfo, ClassReader}; 10 | 11 | #[derive(Default)] 12 | pub struct SignatureAttribute { 13 | constant_pool: RcRefCell, 14 | signature_index: u16, 15 | } 16 | 17 | impl AttributeInfo for SignatureAttribute { 18 | fn read_info(&mut self, reader: &mut ClassReader) { 19 | self.signature_index = reader.read_u16(); 20 | } 21 | } 22 | 23 | impl SignatureAttribute { 24 | pub fn new (cp: RcRefCell) -> Self { 25 | let mut sa = SignatureAttribute::default(); 26 | sa.constant_pool = cp; 27 | sa 28 | } 29 | } -------------------------------------------------------------------------------- /ch03_classfile/src/classfile/constant_pool/cp_string.rs: -------------------------------------------------------------------------------- 1 | /// CONSTANT_String_info { 2 | /// u1 tag; 3 | /// u2 string_index; 4 | /// } 5 | 6 | use crate::types::RcRefCell; 7 | use super::{ConstantInfo, ClassReader, ConstantPool}; 8 | 9 | pub struct ConstantStringInfo { 10 | constant_pool: RcRefCell, 11 | string_index: u16 12 | } 13 | 14 | impl ConstantInfo for ConstantStringInfo { 15 | fn read_info(&mut self, reader: &mut ClassReader) { 16 | self.string_index = reader.read_u16(); 17 | } 18 | 19 | fn tag(&self) -> u8 { 20 | super::CONSTANT_STRING 21 | } 22 | 23 | } 24 | 25 | impl ConstantStringInfo { 26 | pub fn new(cp: RcRefCell) -> Self { 27 | ConstantStringInfo { 28 | constant_pool: cp, 29 | string_index: 0, 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ch05_instructions/src/classfile/constant_pool/cp_string.rs: -------------------------------------------------------------------------------- 1 | /// CONSTANT_String_info { 2 | /// u1 tag; 3 | /// u2 string_index; 4 | /// } 5 | 6 | use crate::types::RcRefCell; 7 | use super::{ConstantInfo, ClassReader, ConstantPool}; 8 | 9 | pub struct ConstantStringInfo { 10 | constant_pool: RcRefCell, 11 | string_index: u16 12 | } 13 | 14 | impl ConstantInfo for ConstantStringInfo { 15 | fn read_info(&mut self, reader: &mut ClassReader) { 16 | self.string_index = reader.read_u16(); 17 | } 18 | 19 | fn tag(&self) -> u8 { 20 | super::CONSTANT_STRING 21 | } 22 | 23 | } 24 | 25 | impl ConstantStringInfo { 26 | pub fn new(cp: RcRefCell) -> Self { 27 | ConstantStringInfo { 28 | constant_pool: cp, 29 | string_index: 0, 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ch07_method_invoke/src/classfile/attribute_info/attr_constant_value.rs: -------------------------------------------------------------------------------- 1 | /// ConstantValue_attribute { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u2 constantvalue_index; 5 | /// } 6 | 7 | use super::{AttributeInfo, ClassReader}; 8 | 9 | #[derive(Default)] 10 | pub struct ConstantValueAttribute { 11 | constant_value_index: u16, 12 | } 13 | 14 | impl AttributeInfo for ConstantValueAttribute { 15 | fn read_info(&mut self, reader: &mut ClassReader) { 16 | self.constant_value_index = reader.read_u16(); 17 | } 18 | 19 | fn name(&self) -> &str { 20 | return "ConstantValue"; 21 | } 22 | 23 | fn as_any(&self) -> &dyn std::any::Any { 24 | self 25 | } 26 | } 27 | 28 | impl ConstantValueAttribute { 29 | pub fn constant_value_index(&self) -> u16 { 30 | self.constant_value_index 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ch08_array_string/src/classfile/attribute_info/attr_constant_value.rs: -------------------------------------------------------------------------------- 1 | /// ConstantValue_attribute { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u2 constantvalue_index; 5 | /// } 6 | 7 | use super::{AttributeInfo, ClassReader}; 8 | 9 | #[derive(Default)] 10 | pub struct ConstantValueAttribute { 11 | constant_value_index: u16, 12 | } 13 | 14 | impl AttributeInfo for ConstantValueAttribute { 15 | fn read_info(&mut self, reader: &mut ClassReader) { 16 | self.constant_value_index = reader.read_u16(); 17 | } 18 | 19 | fn name(&self) -> &str { 20 | return "ConstantValue"; 21 | } 22 | 23 | fn as_any(&self) -> &dyn std::any::Any { 24 | self 25 | } 26 | } 27 | 28 | impl ConstantValueAttribute { 29 | pub fn constant_value_index(&self) -> u16 { 30 | self.constant_value_index 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ch10_exception/src/classfile/attribute_info/attr_constant_value.rs: -------------------------------------------------------------------------------- 1 | /// ConstantValue_attribute { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u2 constantvalue_index; 5 | /// } 6 | 7 | use super::{AttributeInfo, ClassReader}; 8 | 9 | #[derive(Default)] 10 | pub struct ConstantValueAttribute { 11 | constant_value_index: u16, 12 | } 13 | 14 | impl AttributeInfo for ConstantValueAttribute { 15 | fn read_info(&mut self, reader: &mut ClassReader) { 16 | self.constant_value_index = reader.read_u16(); 17 | } 18 | 19 | fn name(&self) -> &str { 20 | return "ConstantValue"; 21 | } 22 | 23 | fn as_any(&self) -> &dyn std::any::Any { 24 | self 25 | } 26 | } 27 | 28 | impl ConstantValueAttribute { 29 | pub fn constant_value_index(&self) -> u16 { 30 | self.constant_value_index 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ch09_native/README.md: -------------------------------------------------------------------------------- 1 | ### Chapter 9: 本地方法调用 2 | 3 | #### 编译: 4 | 5 | ```shell 6 | jvm-rust ❯ cargo build -p ch09_native 7 | ``` 8 | 9 | #### 运行: 10 | 11 | ```shell 12 | jvm-rust ❯ ./target/debug/ch09_native -cp "/Users/dxx/Desktop" jvmrust.ch09.GetClassTest 13 | void 14 | boolean 15 | byte 16 | char 17 | short 18 | int 19 | long 20 | float 21 | double 22 | java.lang.Object 23 | jvmrust.ch09.GetClassTest 24 | [I 25 | [[I 26 | [Ljava.lang.Object; 27 | [[Ljava.lang.Object; 28 | java.lang.Runnable 29 | java.lang.String 30 | [D 31 | [Ljava.lang.String; 32 | ``` 33 | 34 | ```shell 35 | jvm-rust ❯ ./target/debug/ch09_native -cp "/Users/dxx/Desktop" jvmrust.ch09.StringTest 36 | true 37 | false 38 | true 39 | ``` 40 | 41 | ```shell 42 | jvm-rust ❯ ./target/debug/ch09_native -cp "/Users/dxx/Desktop" jvmrust.ch09.ObjectTest 43 | 22415000 44 | jvmrust.ch09.ObjectTest@1560698 45 | false 46 | true 47 | ``` -------------------------------------------------------------------------------- /ch04_rtda/src/classfile/attribute_info/attr_unparsed.rs: -------------------------------------------------------------------------------- 1 | /// attribute_info { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u1 info[attribute_length]; 5 | /// } 6 | 7 | use super::{AttributeInfo, ClassReader}; 8 | 9 | pub struct UnparsedAttribute { 10 | name: String, 11 | length: u32, 12 | info: Option>, 13 | } 14 | 15 | impl AttributeInfo for UnparsedAttribute { 16 | fn read_info(&mut self, reader: &mut ClassReader) { 17 | self.info = Some(reader.read_bytes(self.length as usize)); 18 | } 19 | } 20 | 21 | impl UnparsedAttribute { 22 | pub fn new(name: String, length: u32, info: Option>) -> Self { 23 | UnparsedAttribute { 24 | name, length, info 25 | } 26 | } 27 | 28 | pub fn info(&self) -> &Option> { 29 | &self.info 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /ch02_classpath/README.md: -------------------------------------------------------------------------------- 1 | ### Chapter 2: 查找 Class 文件 2 | 3 | #### 编译: 4 | 5 | ```shell 6 | jvm-rust ❯ cargo build -p ch02_classpath 7 | ``` 8 | 9 | #### 运行: 10 | 11 | ```shell 12 | jvm-rust ❯ ./target/debug/ch02_classpath -cp "/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre" java.lang.Object 13 | classpath: /Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre class: java.lang.Object args: [] 14 | class data: [202, 254, 186, 190, 0, 0, 0, 52, 0, 78, 7, 0, 49, 10, 0, 1, 0, 50, 10, 0, 17, 0, 51, 10, 0, 52, 0, 53, 10, 0, 1, 0, 54, 8, 0, 55, 10, 0, 17, 0, 56, 10, 0, 57, 0, 58, 10, 0, 1, 0, 59, 7, 0, 60, 8, 0, 61, 10, 0, 10, 0, 62, 3, 0, 15, 66, 63, 8, 0, 63, 10, 0, 17, 0, 64, 10, 0, 17, 0, 65, 7, 0, 66, 1, 0, 6, 60, 105, 110, 105, 116, 62, 1, 0, 3, 40, 41, 86, 1, 0, 4, 67, 111, 100, 101, 1, 0, 15, 76, 105, 110, 101, 78, 117, 109, 98, 101, 114, 84, 97, 98, ... 15 | ``` 16 | -------------------------------------------------------------------------------- /ch03_classfile/src/classfile/attribute_info/attr_unparsed.rs: -------------------------------------------------------------------------------- 1 | /// attribute_info { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u1 info[attribute_length]; 5 | /// } 6 | 7 | use super::{AttributeInfo, ClassReader}; 8 | 9 | pub struct UnparsedAttribute { 10 | name: String, 11 | length: u32, 12 | info: Option>, 13 | } 14 | 15 | impl AttributeInfo for UnparsedAttribute { 16 | fn read_info(&mut self, reader: &mut ClassReader) { 17 | self.info = Some(reader.read_bytes(self.length as usize)); 18 | } 19 | } 20 | 21 | impl UnparsedAttribute { 22 | pub fn new(name: String, length: u32, info: Option>) -> Self { 23 | UnparsedAttribute { 24 | name, length, info 25 | } 26 | } 27 | 28 | pub fn info(&self) -> &Option> { 29 | &self.info 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /ch04_rtda/src/classfile/attribute_info/attr_source_file.rs: -------------------------------------------------------------------------------- 1 | /// Signature_attribute { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u2 signature_index; 5 | /// } 6 | 7 | use crate::types::RcRefCell; 8 | use super::ConstantPool; 9 | use super::{AttributeInfo, ClassReader}; 10 | 11 | #[derive(Default)] 12 | pub struct SourceFileAttribute { 13 | constant_pool: RcRefCell, 14 | source_file_index: u16, 15 | } 16 | 17 | impl AttributeInfo for SourceFileAttribute { 18 | fn read_info(&mut self, reader: &mut ClassReader) { 19 | self.source_file_index = reader.read_u16(); 20 | } 21 | } 22 | 23 | impl SourceFileAttribute { 24 | pub fn new (cp: RcRefCell) -> Self { 25 | let mut sfa = SourceFileAttribute::default(); 26 | sfa.constant_pool = cp; 27 | sfa 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ch09_native/src/instructions/math/iinc.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | use super::super::bytecode_reader::BytecodeReader; 6 | 7 | /// Increment local variable by constant 8 | #[derive(Default, Debug)] 9 | pub struct IINC { 10 | pub index: usize, 11 | pub _const: i32, 12 | } 13 | 14 | impl Instruction for IINC { 15 | fn fetch_operands(&mut self, reader: &mut BytecodeReader) { 16 | self.index = reader.read_u8() as usize; 17 | self._const = reader.read_i8() as i32; 18 | } 19 | 20 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 21 | let local_vars = frame.local_vars_mut(); 22 | let val = local_vars.get_int(self.index); 23 | let val = val + self._const; 24 | local_vars.set_int(self.index, val); 25 | 26 | Ok(()) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ch09_native/src/native/java/lang/Object.rs: -------------------------------------------------------------------------------- 1 | use crate::rtda::Frame; 2 | use super::registry; 3 | 4 | const J_OBJECT: &str = "java/lang/Object"; 5 | 6 | pub fn init() { 7 | registry(J_OBJECT.into(), "getClass".into(), "()Ljava/lang/Class;".into(), get_class); 8 | registry(J_OBJECT.into(), "hashCode".into(), "()I".into(), hash_code); 9 | } 10 | 11 | /// public final native Class getClass(); 12 | /// ()Ljava/lang/Class; 13 | fn get_class(frame: &mut Frame) { 14 | let this = frame.local_vars_mut().get_this(); 15 | let class = this.unwrap().borrow().class().borrow().j_class(); 16 | frame.operand_stack_mut().push_ref(class); 17 | } 18 | 19 | /// public native int hashCode(); 20 | /// ()I 21 | fn hash_code(frame: &mut Frame) { 22 | let this = frame.local_vars_mut().get_this(); 23 | let hash = this.unwrap().as_ptr() as i32; 24 | frame.operand_stack_mut().push_int(hash); 25 | } 26 | -------------------------------------------------------------------------------- /ch10_exception/src/instructions/references/mod.rs: -------------------------------------------------------------------------------- 1 | mod anewarray; 2 | mod arraylength; 3 | mod athrow; 4 | mod multianewarray; 5 | mod new; 6 | mod newarray; 7 | mod checkcast; 8 | mod getfield; 9 | mod getstatic; 10 | mod instanceof; 11 | mod invokeinterface; 12 | mod invokespecial; 13 | mod invokestatic; 14 | mod invokevirtual; 15 | mod putfield; 16 | mod putstatic; 17 | 18 | pub use self::anewarray::*; 19 | pub use self::arraylength::*; 20 | pub use self::athrow::*; 21 | pub use self::multianewarray::*; 22 | pub use self::new::*; 23 | pub use self::newarray::*; 24 | pub use self::checkcast::*; 25 | pub use self::getfield::*; 26 | pub use self::getstatic::*; 27 | pub use self::instanceof::*; 28 | pub use self::invokeinterface::*; 29 | pub use self::invokespecial::*; 30 | pub use self::invokestatic::*; 31 | pub use self::invokevirtual::*; 32 | pub use self::putfield::*; 33 | pub use self::putstatic::*; 34 | -------------------------------------------------------------------------------- /ch03_classfile/src/classfile/attribute_info/attr_source_file.rs: -------------------------------------------------------------------------------- 1 | /// Signature_attribute { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u2 signature_index; 5 | /// } 6 | 7 | use crate::types::RcRefCell; 8 | use super::ConstantPool; 9 | use super::{AttributeInfo, ClassReader}; 10 | 11 | #[derive(Default)] 12 | pub struct SourceFileAttribute { 13 | constant_pool: RcRefCell, 14 | source_file_index: u16, 15 | } 16 | 17 | impl AttributeInfo for SourceFileAttribute { 18 | fn read_info(&mut self, reader: &mut ClassReader) { 19 | self.source_file_index = reader.read_u16(); 20 | } 21 | } 22 | 23 | impl SourceFileAttribute { 24 | pub fn new (cp: RcRefCell) -> Self { 25 | let mut sfa = SourceFileAttribute::default(); 26 | sfa.constant_pool = cp; 27 | sfa 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ch10_exception/src/instructions/math/iinc.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | use super::super::bytecode_reader::BytecodeReader; 6 | 7 | /// Increment local variable by constant 8 | #[derive(Default, Debug)] 9 | pub struct IINC { 10 | pub index: usize, 11 | pub _const: i32, 12 | } 13 | 14 | impl Instruction for IINC { 15 | fn fetch_operands(&mut self, reader: &mut BytecodeReader) { 16 | self.index = reader.read_u8() as usize; 17 | self._const = reader.read_i8() as i32; 18 | } 19 | 20 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 21 | let local_vars = frame.local_vars_mut(); 22 | let val = local_vars.get_int(self.index); 23 | let val = val + self._const; 24 | local_vars.set_int(self.index, val); 25 | 26 | Ok(()) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ch10_exception/src/native/java/lang/Object.rs: -------------------------------------------------------------------------------- 1 | use crate::rtda::Frame; 2 | use super::registry; 3 | 4 | const J_OBJECT: &str = "java/lang/Object"; 5 | 6 | pub fn init() { 7 | registry(J_OBJECT.into(), "getClass".into(), "()Ljava/lang/Class;".into(), get_class); 8 | registry(J_OBJECT.into(), "hashCode".into(), "()I".into(), hash_code); 9 | } 10 | 11 | /// public final native Class getClass(); 12 | /// ()Ljava/lang/Class; 13 | fn get_class(frame: &mut Frame) { 14 | let this = frame.local_vars_mut().get_this(); 15 | let class = this.unwrap().borrow().class().borrow().j_class(); 16 | frame.operand_stack_mut().push_ref(class); 17 | } 18 | 19 | /// public native int hashCode(); 20 | /// ()I 21 | fn hash_code(frame: &mut Frame) { 22 | let this = frame.local_vars_mut().get_this(); 23 | let hash = this.unwrap().as_ptr() as i32; 24 | frame.operand_stack_mut().push_int(hash); 25 | } 26 | -------------------------------------------------------------------------------- /ch08_array_string/src/instructions/math/iinc.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | use super::super::bytecode_reader::BytecodeReader; 6 | 7 | /// Increment local variable by constant 8 | #[derive(Default, Debug)] 9 | pub struct IINC { 10 | pub index: usize, 11 | pub _const: i32, 12 | } 13 | 14 | impl Instruction for IINC { 15 | fn fetch_operands(&mut self, reader: &mut BytecodeReader) { 16 | self.index = reader.read_u8() as usize; 17 | self._const = reader.read_i8() as i32; 18 | } 19 | 20 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 21 | let local_vars = frame.local_vars_mut(); 22 | let val = local_vars.get_int(self.index); 23 | let val = val + self._const; 24 | local_vars.set_int(self.index, val); 25 | 26 | Ok(()) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ch06_rtda_heap/src/classfile/attribute_info/attr_constant_value.rs: -------------------------------------------------------------------------------- 1 | /// ConstantValue_attribute { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u2 constantvalue_index; 5 | /// } 6 | 7 | use super::{AttributeInfo, ClassReader}; 8 | 9 | #[derive(Default)] 10 | pub struct ConstantValueAttribute { 11 | constant_value_index: u16, 12 | } 13 | 14 | impl AttributeInfo for ConstantValueAttribute { 15 | fn read_info(&mut self, reader: &mut ClassReader) { 16 | self.constant_value_index = reader.read_u16(); 17 | } 18 | 19 | fn name(&self) -> &str { 20 | return "ConstantValue"; 21 | } 22 | 23 | fn as_any(&self) -> &dyn std::any::Any { 24 | self 25 | } 26 | } 27 | 28 | impl ConstantValueAttribute { 29 | pub fn constant_value_index(&self) -> u16 { 30 | self.constant_value_index 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ch05_instructions/README.md: -------------------------------------------------------------------------------- 1 | ### Chapter 5: 指令集和解释器 2 | 3 | #### 编译: 4 | 5 | ```shell 6 | jvm-rust ❯ cargo build -p ch05_instructions 7 | ``` 8 | 9 | #### 运行: 10 | 11 | GaussTest: 12 | 13 | ```java 14 | package jvmrust.ch05; 15 | 16 | public class GaussTest { 17 | 18 | public static void main(String[] args) { 19 | int sum = 0; 20 | for (int i = 1; i <= 100; i++) { 21 | sum += i; 22 | } 23 | System.out.println(sum); 24 | } 25 | 26 | } 27 | ``` 28 | 29 | 指定 classpath 运行 jvmrust.ch05.GaussTest : 30 | 31 | ```shell 32 | jvm-rust ❯ ./target/debug/ch05_instructions -cp "/Users/dxx/Desktop" jvmrust.ch05.GaussTest 33 | ... 34 | LocalVars: LocalVars { slots: [Slot { num: 0, _ref: None }, Slot { num: 5050, _ref: None }, Slot { num: 101, _ref: None }] } 35 | OperandStack: OperandStack { size: 0, slots: [Slot { num: 101, _ref: None }, Slot { num: 100, _ref: None }] } 36 | ``` 37 | -------------------------------------------------------------------------------- /ch05_instructions/src/instructions/math/or.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | // Boolean OR int 7 | #[derive(Default, Debug)] 8 | pub struct IOR; 9 | 10 | impl Instruction for IOR { 11 | fn execute(&mut self, frame: &mut Frame) { 12 | let stack = frame.operand_stack_mut(); 13 | let v2 = stack.pop_int(); 14 | let v1 = stack.pop_int(); 15 | let result = v1 | v2; 16 | stack.push_int(result); 17 | } 18 | } 19 | 20 | // Boolean OR long 21 | #[derive(Default, Debug)] 22 | pub struct LOR; 23 | 24 | impl Instruction for LOR { 25 | fn execute(&mut self, frame: &mut Frame) { 26 | let stack = frame.operand_stack_mut(); 27 | let v2 = stack.pop_long(); 28 | let v1 = stack.pop_long(); 29 | let result = v1 | v2; 30 | stack.push_long(result); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ch06_rtda_heap/src/instructions/math/or.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | // Boolean OR int 7 | #[derive(Default, Debug)] 8 | pub struct IOR; 9 | 10 | impl Instruction for IOR { 11 | fn execute(&mut self, frame: &mut Frame) { 12 | let stack = frame.operand_stack_mut(); 13 | let v2 = stack.pop_int(); 14 | let v1 = stack.pop_int(); 15 | let result = v1 | v2; 16 | stack.push_int(result); 17 | } 18 | } 19 | 20 | // Boolean OR long 21 | #[derive(Default, Debug)] 22 | pub struct LOR; 23 | 24 | impl Instruction for LOR { 25 | fn execute(&mut self, frame: &mut Frame) { 26 | let stack = frame.operand_stack_mut(); 27 | let v2 = stack.pop_long(); 28 | let v1 = stack.pop_long(); 29 | let result = v1 | v2; 30 | stack.push_long(result); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ch06_rtda_heap/src/instructions/math/xor.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | // Boolean XOR int 7 | #[derive(Default, Debug)] 8 | pub struct IXOR; 9 | 10 | impl Instruction for IXOR { 11 | fn execute(&mut self, frame: &mut Frame) { 12 | let stack = frame.operand_stack_mut(); 13 | let v1 = stack.pop_int(); 14 | let v2 = stack.pop_int(); 15 | let result = v1 ^ v2; 16 | stack.push_int(result); 17 | } 18 | } 19 | 20 | // Boolean XOR long 21 | #[derive(Default, Debug)] 22 | pub struct LXOR; 23 | 24 | impl Instruction for LXOR { 25 | fn execute(&mut self, frame: &mut Frame) { 26 | let stack = frame.operand_stack_mut(); 27 | let v1 = stack.pop_long(); 28 | let v2 = stack.pop_long(); 29 | let result = v1 ^ v2; 30 | stack.push_long(result); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ch07_method_invoke/src/instructions/math/or.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | // Boolean OR int 7 | #[derive(Default, Debug)] 8 | pub struct IOR; 9 | 10 | impl Instruction for IOR { 11 | fn execute(&mut self, frame: &mut Frame) { 12 | let stack = frame.operand_stack_mut(); 13 | let v2 = stack.pop_int(); 14 | let v1 = stack.pop_int(); 15 | let result = v1 | v2; 16 | stack.push_int(result); 17 | } 18 | } 19 | 20 | // Boolean OR long 21 | #[derive(Default, Debug)] 22 | pub struct LOR; 23 | 24 | impl Instruction for LOR { 25 | fn execute(&mut self, frame: &mut Frame) { 26 | let stack = frame.operand_stack_mut(); 27 | let v2 = stack.pop_long(); 28 | let v1 = stack.pop_long(); 29 | let result = v1 | v2; 30 | stack.push_long(result); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ch05_instructions/src/instructions/math/xor.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | // Boolean XOR int 7 | #[derive(Default, Debug)] 8 | pub struct IXOR; 9 | 10 | impl Instruction for IXOR { 11 | fn execute(&mut self, frame: &mut Frame) { 12 | let stack = frame.operand_stack_mut(); 13 | let v1 = stack.pop_int(); 14 | let v2 = stack.pop_int(); 15 | let result = v1 ^ v2; 16 | stack.push_int(result); 17 | } 18 | } 19 | 20 | // Boolean XOR long 21 | #[derive(Default, Debug)] 22 | pub struct LXOR; 23 | 24 | impl Instruction for LXOR { 25 | fn execute(&mut self, frame: &mut Frame) { 26 | let stack = frame.operand_stack_mut(); 27 | let v1 = stack.pop_long(); 28 | let v2 = stack.pop_long(); 29 | let result = v1 ^ v2; 30 | stack.push_long(result); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ch06_rtda_heap/src/instructions/math/and.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | // Boolean AND int 7 | 8 | #[derive(Default, Debug)] 9 | pub struct IAND; 10 | 11 | impl Instruction for IAND { 12 | fn execute(&mut self, frame: &mut Frame) { 13 | let stack = frame.operand_stack_mut(); 14 | let v2 = stack.pop_int(); 15 | let v1 = stack.pop_int(); 16 | let result = v1 & v2; 17 | stack.push_int(result); 18 | } 19 | } 20 | 21 | // Boolean AND long 22 | #[derive(Default, Debug)] 23 | pub struct LAND; 24 | 25 | impl Instruction for LAND { 26 | fn execute(&mut self, frame: &mut Frame) { 27 | let stack = frame.operand_stack_mut(); 28 | let v2 = stack.pop_long(); 29 | let v1 = stack.pop_long(); 30 | let result = v1 & v2; 31 | stack.push_long(result); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ch07_method_invoke/src/instructions/math/xor.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | // Boolean XOR int 7 | #[derive(Default, Debug)] 8 | pub struct IXOR; 9 | 10 | impl Instruction for IXOR { 11 | fn execute(&mut self, frame: &mut Frame) { 12 | let stack = frame.operand_stack_mut(); 13 | let v1 = stack.pop_int(); 14 | let v2 = stack.pop_int(); 15 | let result = v1 ^ v2; 16 | stack.push_int(result); 17 | } 18 | } 19 | 20 | // Boolean XOR long 21 | #[derive(Default, Debug)] 22 | pub struct LXOR; 23 | 24 | impl Instruction for LXOR { 25 | fn execute(&mut self, frame: &mut Frame) { 26 | let stack = frame.operand_stack_mut(); 27 | let v1 = stack.pop_long(); 28 | let v2 = stack.pop_long(); 29 | let result = v1 ^ v2; 30 | stack.push_long(result); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ch05_instructions/src/instructions/math/and.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | // Boolean AND int 7 | 8 | #[derive(Default, Debug)] 9 | pub struct IAND; 10 | 11 | impl Instruction for IAND { 12 | fn execute(&mut self, frame: &mut Frame) { 13 | let stack = frame.operand_stack_mut(); 14 | let v2 = stack.pop_int(); 15 | let v1 = stack.pop_int(); 16 | let result = v1 & v2; 17 | stack.push_int(result); 18 | } 19 | } 20 | 21 | // Boolean AND long 22 | #[derive(Default, Debug)] 23 | pub struct LAND; 24 | 25 | impl Instruction for LAND { 26 | fn execute(&mut self, frame: &mut Frame) { 27 | let stack = frame.operand_stack_mut(); 28 | let v2 = stack.pop_long(); 29 | let v1 = stack.pop_long(); 30 | let result = v1 & v2; 31 | stack.push_long(result); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ch07_method_invoke/src/instructions/math/and.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | // Boolean AND int 7 | 8 | #[derive(Default, Debug)] 9 | pub struct IAND; 10 | 11 | impl Instruction for IAND { 12 | fn execute(&mut self, frame: &mut Frame) { 13 | let stack = frame.operand_stack_mut(); 14 | let v2 = stack.pop_int(); 15 | let v1 = stack.pop_int(); 16 | let result = v1 & v2; 17 | stack.push_int(result); 18 | } 19 | } 20 | 21 | // Boolean AND long 22 | #[derive(Default, Debug)] 23 | pub struct LAND; 24 | 25 | impl Instruction for LAND { 26 | fn execute(&mut self, frame: &mut Frame) { 27 | let stack = frame.operand_stack_mut(); 28 | let v2 = stack.pop_long(); 29 | let v1 = stack.pop_long(); 30 | let result = v1 & v2; 31 | stack.push_long(result); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ch09_native/src/native/java/lang/Float.rs: -------------------------------------------------------------------------------- 1 | use crate::rtda::Frame; 2 | use super::registry; 3 | 4 | const J_FLOAT: &str = "java/lang/Float"; 5 | 6 | pub fn init() { 7 | registry(J_FLOAT.into(), "floatToRawIntBits".into(), "(F)I".into(), float_to_raw_int_bits); 8 | registry(J_FLOAT.into(), "intBitsToFloat".into(), "(I)F".into(), int_bits_to_float); 9 | } 10 | 11 | /// public static native int floatToRawIntBits(float value); 12 | /// (F)I 13 | fn float_to_raw_int_bits(frame: &mut Frame) { 14 | let value = frame.local_vars_mut().get_float(0); 15 | let bits = f32::to_bits(value); 16 | frame.operand_stack_mut().push_int(bits as i32); 17 | } 18 | 19 | /// public static native float intBitsToFloat(int bits); 20 | /// (I)F 21 | fn int_bits_to_float(frame: &mut Frame) { 22 | let bits = frame.local_vars_mut().get_int(0); 23 | let value = f32::from_bits(bits as u32); 24 | frame.operand_stack_mut().push_float(value); 25 | } 26 | -------------------------------------------------------------------------------- /ch10_exception/src/native/java/lang/Float.rs: -------------------------------------------------------------------------------- 1 | use crate::rtda::Frame; 2 | use super::registry; 3 | 4 | const J_FLOAT: &str = "java/lang/Float"; 5 | 6 | pub fn init() { 7 | registry(J_FLOAT.into(), "floatToRawIntBits".into(), "(F)I".into(), float_to_raw_int_bits); 8 | registry(J_FLOAT.into(), "intBitsToFloat".into(), "(I)F".into(), int_bits_to_float); 9 | } 10 | 11 | /// public static native int floatToRawIntBits(float value); 12 | /// (F)I 13 | fn float_to_raw_int_bits(frame: &mut Frame) { 14 | let value = frame.local_vars_mut().get_float(0); 15 | let bits = f32::to_bits(value); 16 | frame.operand_stack_mut().push_int(bits as i32); 17 | } 18 | 19 | /// public static native float intBitsToFloat(int bits); 20 | /// (I)F 21 | fn int_bits_to_float(frame: &mut Frame) { 22 | let bits = frame.local_vars_mut().get_int(0); 23 | let value = f32::from_bits(bits as u32); 24 | frame.operand_stack_mut().push_float(value); 25 | } 26 | -------------------------------------------------------------------------------- /ch02_classpath/src/main.rs: -------------------------------------------------------------------------------- 1 | mod cmd; 2 | mod classpath; 3 | 4 | use crate::cmd::{parse_cmd, Cmd}; 5 | use crate::classpath::{Classpath, entry::Entry}; 6 | 7 | fn main() { 8 | let cmd = parse_cmd(); 9 | 10 | if cmd.version_flag { 11 | println!("{}", "version 0.0.1"); 12 | } else if cmd.help_flag || cmd.class == "" { 13 | cmd.print_usage(); 14 | } else { 15 | start_jvm(cmd); 16 | } 17 | } 18 | 19 | fn start_jvm(cmd: Cmd) { 20 | let mut cp = Classpath::parse(&cmd.x_jre_option, &cmd.cp_option); 21 | 22 | println!("classpath: {} class: {} args: {:?}", cp, cmd.class, cmd.args); 23 | 24 | let class_name = cmd.class.replace(".", "/"); 25 | let class_data = match cp.read_class(&class_name) { 26 | Ok(class_data) => class_data, 27 | Err(err) => { panic!("Could not find or load main class {}: {}", cmd.class, err); }, 28 | }; 29 | println!("class data: {:?}", class_data); 30 | } 31 | -------------------------------------------------------------------------------- /ch09_native/src/classfile/attribute_info/attr_source_file.rs: -------------------------------------------------------------------------------- 1 | /// Signature_attribute { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u2 signature_index; 5 | /// } 6 | 7 | use crate::types::RcRefCell; 8 | use super::ConstantPool; 9 | use super::{AttributeInfo, ClassReader}; 10 | 11 | #[derive(Default)] 12 | pub struct SourceFileAttribute { 13 | constant_pool: RcRefCell, 14 | source_file_index: u16, 15 | } 16 | 17 | impl AttributeInfo for SourceFileAttribute { 18 | fn read_info(&mut self, reader: &mut ClassReader) { 19 | self.source_file_index = reader.read_u16(); 20 | } 21 | 22 | fn as_any(&self) -> &dyn std::any::Any { 23 | self 24 | } 25 | } 26 | 27 | impl SourceFileAttribute { 28 | pub fn new (cp: RcRefCell) -> Self { 29 | let mut sfa = SourceFileAttribute::default(); 30 | sfa.constant_pool = cp; 31 | sfa 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ch09_native/src/classfile/attribute_info/attr_unparsed.rs: -------------------------------------------------------------------------------- 1 | /// attribute_info { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u1 info[attribute_length]; 5 | /// } 6 | 7 | use super::{AttributeInfo, ClassReader}; 8 | 9 | pub struct UnparsedAttribute { 10 | name: String, 11 | length: u32, 12 | info: Option>, 13 | } 14 | 15 | impl AttributeInfo for UnparsedAttribute { 16 | fn read_info(&mut self, reader: &mut ClassReader) { 17 | self.info = Some(reader.read_bytes(self.length as usize)); 18 | } 19 | 20 | fn as_any(&self) -> &dyn std::any::Any { 21 | self 22 | } 23 | } 24 | 25 | impl UnparsedAttribute { 26 | pub fn new(name: String, length: u32, info: Option>) -> Self { 27 | UnparsedAttribute { 28 | name, length, info 29 | } 30 | } 31 | 32 | pub fn info(&self) -> &Option> { 33 | &self.info 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /ch10_exception/src/classfile/attribute_info/attr_unparsed.rs: -------------------------------------------------------------------------------- 1 | /// attribute_info { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u1 info[attribute_length]; 5 | /// } 6 | 7 | use super::{AttributeInfo, ClassReader}; 8 | 9 | pub struct UnparsedAttribute { 10 | name: String, 11 | length: u32, 12 | info: Option>, 13 | } 14 | 15 | impl AttributeInfo for UnparsedAttribute { 16 | fn read_info(&mut self, reader: &mut ClassReader) { 17 | self.info = Some(reader.read_bytes(self.length as usize)); 18 | } 19 | 20 | fn as_any(&self) -> &dyn std::any::Any { 21 | self 22 | } 23 | } 24 | 25 | impl UnparsedAttribute { 26 | pub fn new(name: String, length: u32, info: Option>) -> Self { 27 | UnparsedAttribute { 28 | name, length, info 29 | } 30 | } 31 | 32 | pub fn info(&self) -> &Option> { 33 | &self.info 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /ch07_method_invoke/src/classfile/attribute_info/attr_unparsed.rs: -------------------------------------------------------------------------------- 1 | /// attribute_info { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u1 info[attribute_length]; 5 | /// } 6 | 7 | use super::{AttributeInfo, ClassReader}; 8 | 9 | pub struct UnparsedAttribute { 10 | name: String, 11 | length: u32, 12 | info: Option>, 13 | } 14 | 15 | impl AttributeInfo for UnparsedAttribute { 16 | fn read_info(&mut self, reader: &mut ClassReader) { 17 | self.info = Some(reader.read_bytes(self.length as usize)); 18 | } 19 | 20 | fn as_any(&self) -> &dyn std::any::Any { 21 | self 22 | } 23 | } 24 | 25 | impl UnparsedAttribute { 26 | pub fn new(name: String, length: u32, info: Option>) -> Self { 27 | UnparsedAttribute { 28 | name, length, info 29 | } 30 | } 31 | 32 | pub fn info(&self) -> &Option> { 33 | &self.info 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /ch08_array_string/src/classfile/attribute_info/attr_source_file.rs: -------------------------------------------------------------------------------- 1 | /// Signature_attribute { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u2 signature_index; 5 | /// } 6 | 7 | use crate::types::RcRefCell; 8 | use super::ConstantPool; 9 | use super::{AttributeInfo, ClassReader}; 10 | 11 | #[derive(Default)] 12 | pub struct SourceFileAttribute { 13 | constant_pool: RcRefCell, 14 | source_file_index: u16, 15 | } 16 | 17 | impl AttributeInfo for SourceFileAttribute { 18 | fn read_info(&mut self, reader: &mut ClassReader) { 19 | self.source_file_index = reader.read_u16(); 20 | } 21 | 22 | fn as_any(&self) -> &dyn std::any::Any { 23 | self 24 | } 25 | } 26 | 27 | impl SourceFileAttribute { 28 | pub fn new (cp: RcRefCell) -> Self { 29 | let mut sfa = SourceFileAttribute::default(); 30 | sfa.constant_pool = cp; 31 | sfa 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ch08_array_string/src/classfile/attribute_info/attr_unparsed.rs: -------------------------------------------------------------------------------- 1 | /// attribute_info { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u1 info[attribute_length]; 5 | /// } 6 | 7 | use super::{AttributeInfo, ClassReader}; 8 | 9 | pub struct UnparsedAttribute { 10 | name: String, 11 | length: u32, 12 | info: Option>, 13 | } 14 | 15 | impl AttributeInfo for UnparsedAttribute { 16 | fn read_info(&mut self, reader: &mut ClassReader) { 17 | self.info = Some(reader.read_bytes(self.length as usize)); 18 | } 19 | 20 | fn as_any(&self) -> &dyn std::any::Any { 21 | self 22 | } 23 | } 24 | 25 | impl UnparsedAttribute { 26 | pub fn new(name: String, length: u32, info: Option>) -> Self { 27 | UnparsedAttribute { 28 | name, length, info 29 | } 30 | } 31 | 32 | pub fn info(&self) -> &Option> { 33 | &self.info 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /ch07_method_invoke/src/classfile/attribute_info/attr_source_file.rs: -------------------------------------------------------------------------------- 1 | /// Signature_attribute { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u2 signature_index; 5 | /// } 6 | 7 | use crate::types::RcRefCell; 8 | use super::ConstantPool; 9 | use super::{AttributeInfo, ClassReader}; 10 | 11 | #[derive(Default)] 12 | pub struct SourceFileAttribute { 13 | constant_pool: RcRefCell, 14 | source_file_index: u16, 15 | } 16 | 17 | impl AttributeInfo for SourceFileAttribute { 18 | fn read_info(&mut self, reader: &mut ClassReader) { 19 | self.source_file_index = reader.read_u16(); 20 | } 21 | 22 | fn as_any(&self) -> &dyn std::any::Any { 23 | self 24 | } 25 | } 26 | 27 | impl SourceFileAttribute { 28 | pub fn new (cp: RcRefCell) -> Self { 29 | let mut sfa = SourceFileAttribute::default(); 30 | sfa.constant_pool = cp; 31 | sfa 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ch09_native/src/native/java/lang/Double.rs: -------------------------------------------------------------------------------- 1 | use crate::rtda::Frame; 2 | use super::registry; 3 | 4 | const J_DOUBLE: &str = "java/lang/Double"; 5 | 6 | pub fn init() { 7 | registry(J_DOUBLE.into(), "doubleToRawLongBits".into(), "(D)J".into(), double_to_raw_long_bits); 8 | registry(J_DOUBLE.into(), "longBitsToDouble".into(), "(J)D".into(), long_bits_to_double); 9 | } 10 | 11 | /// public static native long doubleToRawLongBits(double value); 12 | /// (D)J 13 | fn double_to_raw_long_bits(frame: &mut Frame) { 14 | let value = frame.local_vars_mut().get_double(0); 15 | let bits = f64::to_bits(value); 16 | frame.operand_stack_mut().push_long(bits as i64); 17 | } 18 | 19 | /// public static native double longBitsToDouble(long bits); 20 | /// (J)D 21 | fn long_bits_to_double(frame: &mut Frame) { 22 | let bits = frame.local_vars_mut().get_long(0); 23 | let value = f64::from_bits(bits as u64); 24 | frame.operand_stack_mut().push_double(value); 25 | } 26 | -------------------------------------------------------------------------------- /ch04_rtda/src/classfile/attribute_info/attr_markers.rs: -------------------------------------------------------------------------------- 1 | /// Deprecated_attribute { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// } 5 | 6 | use super::{AttributeInfo, ClassReader}; 7 | 8 | #[derive(Default)] 9 | pub struct DeprecatedAttribute { 10 | 11 | } 12 | 13 | impl AttributeInfo for DeprecatedAttribute { 14 | fn read_info(&mut self, _reader: &mut ClassReader) { 15 | 16 | } 17 | } 18 | 19 | /// Synthetic_attribute { 20 | /// u2 attribute_name_index; 21 | /// u4 attribute_length; 22 | /// } 23 | 24 | #[derive(Default)] 25 | pub struct SyntheticAttribute {} 26 | 27 | impl AttributeInfo for SyntheticAttribute { 28 | fn read_info(&mut self, _reader: &mut ClassReader) { 29 | 30 | } 31 | } 32 | 33 | pub struct MarkerAttribute { 34 | 35 | } 36 | 37 | impl AttributeInfo for MarkerAttribute { 38 | fn read_info(&mut self, _reader: &mut ClassReader) { 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /ch10_exception/src/native/java/lang/Double.rs: -------------------------------------------------------------------------------- 1 | use crate::rtda::Frame; 2 | use super::registry; 3 | 4 | const J_DOUBLE: &str = "java/lang/Double"; 5 | 6 | pub fn init() { 7 | registry(J_DOUBLE.into(), "doubleToRawLongBits".into(), "(D)J".into(), double_to_raw_long_bits); 8 | registry(J_DOUBLE.into(), "longBitsToDouble".into(), "(J)D".into(), long_bits_to_double); 9 | } 10 | 11 | /// public static native long doubleToRawLongBits(double value); 12 | /// (D)J 13 | fn double_to_raw_long_bits(frame: &mut Frame) { 14 | let value = frame.local_vars_mut().get_double(0); 15 | let bits = f64::to_bits(value); 16 | frame.operand_stack_mut().push_long(bits as i64); 17 | } 18 | 19 | /// public static native double longBitsToDouble(long bits); 20 | /// (J)D 21 | fn long_bits_to_double(frame: &mut Frame) { 22 | let bits = frame.local_vars_mut().get_long(0); 23 | let value = f64::from_bits(bits as u64); 24 | frame.operand_stack_mut().push_double(value); 25 | } 26 | -------------------------------------------------------------------------------- /ch03_classfile/src/classfile/attribute_info/attr_markers.rs: -------------------------------------------------------------------------------- 1 | /// Deprecated_attribute { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// } 5 | 6 | use super::{AttributeInfo, ClassReader}; 7 | 8 | #[derive(Default)] 9 | pub struct DeprecatedAttribute { 10 | 11 | } 12 | 13 | impl AttributeInfo for DeprecatedAttribute { 14 | fn read_info(&mut self, _reader: &mut ClassReader) { 15 | 16 | } 17 | } 18 | 19 | /// Synthetic_attribute { 20 | /// u2 attribute_name_index; 21 | /// u4 attribute_length; 22 | /// } 23 | 24 | #[derive(Default)] 25 | pub struct SyntheticAttribute {} 26 | 27 | impl AttributeInfo for SyntheticAttribute { 28 | fn read_info(&mut self, _reader: &mut ClassReader) { 29 | 30 | } 31 | } 32 | 33 | pub struct MarkerAttribute { 34 | 35 | } 36 | 37 | impl AttributeInfo for MarkerAttribute { 38 | fn read_info(&mut self, _reader: &mut ClassReader) { 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /ch06_rtda_heap/src/classfile/attribute_info/attr_source_file.rs: -------------------------------------------------------------------------------- 1 | /// Signature_attribute { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u2 signature_index; 5 | /// } 6 | 7 | use crate::types::RcRefCell; 8 | use super::ConstantPool; 9 | use super::{AttributeInfo, ClassReader}; 10 | 11 | #[derive(Default)] 12 | pub struct SourceFileAttribute { 13 | constant_pool: RcRefCell, 14 | source_file_index: u16, 15 | } 16 | 17 | impl AttributeInfo for SourceFileAttribute { 18 | fn read_info(&mut self, reader: &mut ClassReader) { 19 | self.source_file_index = reader.read_u16(); 20 | } 21 | 22 | fn as_any(&self) -> &dyn std::any::Any { 23 | self 24 | } 25 | } 26 | 27 | impl SourceFileAttribute { 28 | pub fn new (cp: RcRefCell) -> Self { 29 | let mut sfa = SourceFileAttribute::default(); 30 | sfa.constant_pool = cp; 31 | sfa 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ch06_rtda_heap/src/classfile/attribute_info/attr_unparsed.rs: -------------------------------------------------------------------------------- 1 | /// attribute_info { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u1 info[attribute_length]; 5 | /// } 6 | 7 | use super::{AttributeInfo, ClassReader}; 8 | 9 | pub struct UnparsedAttribute { 10 | name: String, 11 | length: u32, 12 | info: Option>, 13 | } 14 | 15 | impl AttributeInfo for UnparsedAttribute { 16 | fn read_info(&mut self, reader: &mut ClassReader) { 17 | self.info = Some(reader.read_bytes(self.length as usize)); 18 | } 19 | 20 | fn as_any(&self) -> &dyn std::any::Any { 21 | self 22 | } 23 | } 24 | 25 | impl UnparsedAttribute { 26 | pub fn new(name: String, length: u32, info: Option>) -> Self { 27 | UnparsedAttribute { 28 | name, length, info 29 | } 30 | } 31 | 32 | pub fn info(&self) -> &Option> { 33 | &self.info 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /ch05_instructions/src/classfile/attribute_info/attr_source_file.rs: -------------------------------------------------------------------------------- 1 | /// Signature_attribute { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u2 signature_index; 5 | /// } 6 | 7 | use crate::types::RcRefCell; 8 | use super::ConstantPool; 9 | use super::{AttributeInfo, ClassReader}; 10 | 11 | #[derive(Default)] 12 | pub struct SourceFileAttribute { 13 | constant_pool: RcRefCell, 14 | source_file_index: u16, 15 | } 16 | 17 | impl AttributeInfo for SourceFileAttribute { 18 | fn read_info(&mut self, reader: &mut ClassReader) { 19 | self.source_file_index = reader.read_u16(); 20 | } 21 | 22 | fn as_any(&self) -> &dyn std::any::Any { 23 | self 24 | } 25 | } 26 | 27 | impl SourceFileAttribute { 28 | pub fn new (cp: RcRefCell) -> Self { 29 | let mut sfa = SourceFileAttribute::default(); 30 | sfa.constant_pool = cp; 31 | sfa 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ch05_instructions/src/classfile/attribute_info/attr_unparsed.rs: -------------------------------------------------------------------------------- 1 | /// attribute_info { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u1 info[attribute_length]; 5 | /// } 6 | 7 | use super::{AttributeInfo, ClassReader}; 8 | 9 | pub struct UnparsedAttribute { 10 | name: String, 11 | length: u32, 12 | info: Option>, 13 | } 14 | 15 | impl AttributeInfo for UnparsedAttribute { 16 | fn read_info(&mut self, reader: &mut ClassReader) { 17 | self.info = Some(reader.read_bytes(self.length as usize)); 18 | } 19 | 20 | fn as_any(&self) -> &dyn std::any::Any { 21 | self 22 | } 23 | } 24 | 25 | impl UnparsedAttribute { 26 | pub fn new(name: String, length: u32, info: Option>) -> Self { 27 | UnparsedAttribute { 28 | name, length, info 29 | } 30 | } 31 | 32 | pub fn info(&self) -> &Option> { 33 | &self.info 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /ch05_instructions/src/instructions/stack/pop.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | /// Pop the top operand stack value 7 | #[derive(Default, Debug)] 8 | pub struct POP; 9 | 10 | impl Instruction for POP { 11 | /// bottom -> top 12 | /// [...][c][b][a] 13 | /// | 14 | /// V 15 | /// [...][c][b] 16 | fn execute(&mut self, frame: &mut Frame) { 17 | frame.operand_stack_mut().pop_slot(); 18 | } 19 | } 20 | 21 | /// Pop the top one or two operand stack values 22 | #[derive(Default, Debug)] 23 | pub struct POP2; 24 | 25 | impl Instruction for POP2 { 26 | /// bottom -> top 27 | /// [...][c][b][a] 28 | /// | | 29 | /// V V 30 | /// [...][c] 31 | fn execute(&mut self, frame: &mut Frame) { 32 | let stack = frame.operand_stack_mut(); 33 | stack.pop_slot(); 34 | stack.pop_slot(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ch06_rtda_heap/src/instructions/stack/pop.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | /// Pop the top operand stack value 7 | #[derive(Default, Debug)] 8 | pub struct POP; 9 | 10 | impl Instruction for POP { 11 | /// bottom -> top 12 | /// [...][c][b][a] 13 | /// | 14 | /// V 15 | /// [...][c][b] 16 | fn execute(&mut self, frame: &mut Frame) { 17 | frame.operand_stack_mut().pop_slot(); 18 | } 19 | } 20 | 21 | /// Pop the top one or two operand stack values 22 | #[derive(Default, Debug)] 23 | pub struct POP2; 24 | 25 | impl Instruction for POP2 { 26 | /// bottom -> top 27 | /// [...][c][b][a] 28 | /// | | 29 | /// V V 30 | /// [...][c] 31 | fn execute(&mut self, frame: &mut Frame) { 32 | let stack = frame.operand_stack_mut(); 33 | stack.pop_slot(); 34 | stack.pop_slot(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ch07_method_invoke/src/instructions/stack/pop.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | /// Pop the top operand stack value 7 | #[derive(Default, Debug)] 8 | pub struct POP; 9 | 10 | impl Instruction for POP { 11 | /// bottom -> top 12 | /// [...][c][b][a] 13 | /// | 14 | /// V 15 | /// [...][c][b] 16 | fn execute(&mut self, frame: &mut Frame) { 17 | frame.operand_stack_mut().pop_slot(); 18 | } 19 | } 20 | 21 | /// Pop the top one or two operand stack values 22 | #[derive(Default, Debug)] 23 | pub struct POP2; 24 | 25 | impl Instruction for POP2 { 26 | /// bottom -> top 27 | /// [...][c][b][a] 28 | /// | | 29 | /// V V 30 | /// [...][c] 31 | fn execute(&mut self, frame: &mut Frame) { 32 | let stack = frame.operand_stack_mut(); 33 | stack.pop_slot(); 34 | stack.pop_slot(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ch05_instructions/src/instructions/comparisons/fcmp.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | /// Compare float 7 | #[derive(Default, Debug)] 8 | pub struct FCMPG; 9 | 10 | impl Instruction for FCMPG { 11 | fn execute(&mut self, frame: &mut Frame) { 12 | _fcmp(frame, true); 13 | } 14 | } 15 | 16 | #[derive(Default, Debug)] 17 | pub struct FCMPL; 18 | 19 | impl Instruction for FCMPL { 20 | fn execute(&mut self, frame: &mut Frame) { 21 | _fcmp(frame, false); 22 | } 23 | } 24 | 25 | fn _fcmp(frame: &mut Frame, g_flag: bool) { 26 | let stack = frame.operand_stack_mut(); 27 | let v2 = stack.pop_float(); 28 | let v1 = stack.pop_float(); 29 | if v1 > v2 { 30 | stack.push_int(1); 31 | } else if v1 == v2 { 32 | stack.push_int(0); 33 | } else if v1 < v2 { 34 | stack.push_int(-1); 35 | } else if g_flag { 36 | stack.push_int(1); 37 | } else { 38 | stack.push_int(-1); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ch06_rtda_heap/src/instructions/comparisons/dcmp.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | /// Compare double 7 | #[derive(Default, Debug)] 8 | pub struct DCMPG; 9 | 10 | impl Instruction for DCMPG { 11 | fn execute(&mut self, frame: &mut Frame) { 12 | _dcmp(frame, true); 13 | } 14 | } 15 | 16 | #[derive(Default, Debug)] 17 | pub struct DCMPL; 18 | 19 | impl Instruction for DCMPL { 20 | fn execute(&mut self, frame: &mut Frame) { 21 | _dcmp(frame, false); 22 | } 23 | } 24 | 25 | fn _dcmp(frame: &mut Frame, g_flag: bool) { 26 | let stack = frame.operand_stack_mut(); 27 | let v2 = stack.pop_double(); 28 | let v1 = stack.pop_double(); 29 | if v1 > v2 { 30 | stack.push_int(1); 31 | } else if v1 == v2 { 32 | stack.push_int(0); 33 | } else if v1 < v2 { 34 | stack.push_int(-1); 35 | } else if g_flag { 36 | stack.push_int(1); 37 | } else { 38 | stack.push_int(-1); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ch06_rtda_heap/src/instructions/comparisons/fcmp.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | /// Compare float 7 | #[derive(Default, Debug)] 8 | pub struct FCMPG; 9 | 10 | impl Instruction for FCMPG { 11 | fn execute(&mut self, frame: &mut Frame) { 12 | _fcmp(frame, true); 13 | } 14 | } 15 | 16 | #[derive(Default, Debug)] 17 | pub struct FCMPL; 18 | 19 | impl Instruction for FCMPL { 20 | fn execute(&mut self, frame: &mut Frame) { 21 | _fcmp(frame, false); 22 | } 23 | } 24 | 25 | fn _fcmp(frame: &mut Frame, g_flag: bool) { 26 | let stack = frame.operand_stack_mut(); 27 | let v2 = stack.pop_float(); 28 | let v1 = stack.pop_float(); 29 | if v1 > v2 { 30 | stack.push_int(1); 31 | } else if v1 == v2 { 32 | stack.push_int(0); 33 | } else if v1 < v2 { 34 | stack.push_int(-1); 35 | } else if g_flag { 36 | stack.push_int(1); 37 | } else { 38 | stack.push_int(-1); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ch09_native/src/classfile/constant_pool/cp_name_and_type.rs: -------------------------------------------------------------------------------- 1 | /// CONSTANT_NameAndType_info { 2 | /// u1 tag; 3 | /// u2 name_index; 4 | /// u2 descriptor_index; 5 | /// } 6 | 7 | use super::{ConstantInfo, ClassReader}; 8 | 9 | #[derive(Default)] 10 | pub struct ConstantNameAndTypeInfo { 11 | name_index: u16, 12 | descriptor_index: u16, 13 | } 14 | 15 | impl ConstantInfo for ConstantNameAndTypeInfo { 16 | fn read_info(&mut self, reader: &mut ClassReader) { 17 | self.name_index = reader.read_u16(); 18 | self.descriptor_index = reader.read_u16(); 19 | } 20 | 21 | fn tag(&self) -> u8 { 22 | super::CONSTANT_NAME_AND_TYPE 23 | } 24 | 25 | fn as_any(&self) -> &dyn std::any::Any { 26 | self 27 | } 28 | } 29 | 30 | impl ConstantNameAndTypeInfo { 31 | pub fn name_index(&self) -> u16 { 32 | self.name_index 33 | } 34 | 35 | pub fn descriptor_index(&self) -> u16 { 36 | self.descriptor_index 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /ch05_instructions/src/instructions/comparisons/dcmp.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | /// Compare double 7 | #[derive(Default, Debug)] 8 | pub struct DCMPG; 9 | 10 | impl Instruction for DCMPG { 11 | fn execute(&mut self, frame: &mut Frame) { 12 | _dcmp(frame, true); 13 | } 14 | } 15 | 16 | #[derive(Default, Debug)] 17 | pub struct DCMPL; 18 | 19 | impl Instruction for DCMPL { 20 | fn execute(&mut self, frame: &mut Frame) { 21 | _dcmp(frame, false); 22 | } 23 | } 24 | 25 | fn _dcmp(frame: &mut Frame, g_flag: bool) { 26 | let stack = frame.operand_stack_mut(); 27 | let v2 = stack.pop_double(); 28 | let v1 = stack.pop_double(); 29 | if v1 > v2 { 30 | stack.push_int(1); 31 | } else if v1 == v2 { 32 | stack.push_int(0); 33 | } else if v1 < v2 { 34 | stack.push_int(-1); 35 | } else if g_flag { 36 | stack.push_int(1); 37 | } else { 38 | stack.push_int(-1); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ch07_method_invoke/src/instructions/comparisons/dcmp.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | /// Compare double 7 | #[derive(Default, Debug)] 8 | pub struct DCMPG; 9 | 10 | impl Instruction for DCMPG { 11 | fn execute(&mut self, frame: &mut Frame) { 12 | _dcmp(frame, true); 13 | } 14 | } 15 | 16 | #[derive(Default, Debug)] 17 | pub struct DCMPL; 18 | 19 | impl Instruction for DCMPL { 20 | fn execute(&mut self, frame: &mut Frame) { 21 | _dcmp(frame, false); 22 | } 23 | } 24 | 25 | fn _dcmp(frame: &mut Frame, g_flag: bool) { 26 | let stack = frame.operand_stack_mut(); 27 | let v2 = stack.pop_double(); 28 | let v1 = stack.pop_double(); 29 | if v1 > v2 { 30 | stack.push_int(1); 31 | } else if v1 == v2 { 32 | stack.push_int(0); 33 | } else if v1 < v2 { 34 | stack.push_int(-1); 35 | } else if g_flag { 36 | stack.push_int(1); 37 | } else { 38 | stack.push_int(-1); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ch07_method_invoke/src/instructions/comparisons/fcmp.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | /// Compare float 7 | #[derive(Default, Debug)] 8 | pub struct FCMPG; 9 | 10 | impl Instruction for FCMPG { 11 | fn execute(&mut self, frame: &mut Frame) { 12 | _fcmp(frame, true); 13 | } 14 | } 15 | 16 | #[derive(Default, Debug)] 17 | pub struct FCMPL; 18 | 19 | impl Instruction for FCMPL { 20 | fn execute(&mut self, frame: &mut Frame) { 21 | _fcmp(frame, false); 22 | } 23 | } 24 | 25 | fn _fcmp(frame: &mut Frame, g_flag: bool) { 26 | let stack = frame.operand_stack_mut(); 27 | let v2 = stack.pop_float(); 28 | let v1 = stack.pop_float(); 29 | if v1 > v2 { 30 | stack.push_int(1); 31 | } else if v1 == v2 { 32 | stack.push_int(0); 33 | } else if v1 < v2 { 34 | stack.push_int(-1); 35 | } else if g_flag { 36 | stack.push_int(1); 37 | } else { 38 | stack.push_int(-1); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ch08_array_string/src/classfile/constant_pool/cp_name_and_type.rs: -------------------------------------------------------------------------------- 1 | /// CONSTANT_NameAndType_info { 2 | /// u1 tag; 3 | /// u2 name_index; 4 | /// u2 descriptor_index; 5 | /// } 6 | 7 | use super::{ConstantInfo, ClassReader}; 8 | 9 | #[derive(Default)] 10 | pub struct ConstantNameAndTypeInfo { 11 | name_index: u16, 12 | descriptor_index: u16, 13 | } 14 | 15 | impl ConstantInfo for ConstantNameAndTypeInfo { 16 | fn read_info(&mut self, reader: &mut ClassReader) { 17 | self.name_index = reader.read_u16(); 18 | self.descriptor_index = reader.read_u16(); 19 | } 20 | 21 | fn tag(&self) -> u8 { 22 | super::CONSTANT_NAME_AND_TYPE 23 | } 24 | 25 | fn as_any(&self) -> &dyn std::any::Any { 26 | self 27 | } 28 | } 29 | 30 | impl ConstantNameAndTypeInfo { 31 | pub fn name_index(&self) -> u16 { 32 | self.name_index 33 | } 34 | 35 | pub fn descriptor_index(&self) -> u16 { 36 | self.descriptor_index 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /ch10_exception/src/classfile/constant_pool/cp_name_and_type.rs: -------------------------------------------------------------------------------- 1 | /// CONSTANT_NameAndType_info { 2 | /// u1 tag; 3 | /// u2 name_index; 4 | /// u2 descriptor_index; 5 | /// } 6 | 7 | use super::{ConstantInfo, ClassReader}; 8 | 9 | #[derive(Default)] 10 | pub struct ConstantNameAndTypeInfo { 11 | name_index: u16, 12 | descriptor_index: u16, 13 | } 14 | 15 | impl ConstantInfo for ConstantNameAndTypeInfo { 16 | fn read_info(&mut self, reader: &mut ClassReader) { 17 | self.name_index = reader.read_u16(); 18 | self.descriptor_index = reader.read_u16(); 19 | } 20 | 21 | fn tag(&self) -> u8 { 22 | super::CONSTANT_NAME_AND_TYPE 23 | } 24 | 25 | fn as_any(&self) -> &dyn std::any::Any { 26 | self 27 | } 28 | } 29 | 30 | impl ConstantNameAndTypeInfo { 31 | pub fn name_index(&self) -> u16 { 32 | self.name_index 33 | } 34 | 35 | pub fn descriptor_index(&self) -> u16 { 36 | self.descriptor_index 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /ch04_rtda/src/classfile/constant_pool/cp_class.rs: -------------------------------------------------------------------------------- 1 | /// CONSTANT_Class_info { 2 | /// u1 tag; 3 | /// u2 name_index; 4 | /// } 5 | 6 | use crate::types::RcRefCell; 7 | use super::{ConstantInfo, ClassReader, ConstantPool}; 8 | 9 | #[derive(Clone)] 10 | pub struct ConstantClassInfo { 11 | constant_pool: RcRefCell, 12 | name_index: u16, 13 | } 14 | 15 | impl ConstantInfo for ConstantClassInfo { 16 | fn read_info(&mut self, reader: &mut ClassReader) { 17 | self.name_index = reader.read_u16(); 18 | } 19 | 20 | fn tag(&self) -> u8 { 21 | super::CONSTANT_CLASS 22 | } 23 | } 24 | 25 | impl ConstantClassInfo { 26 | pub fn new(cp: RcRefCell) -> Self { 27 | ConstantClassInfo { 28 | constant_pool: cp, 29 | name_index: 0, 30 | } 31 | } 32 | 33 | pub fn name(&self) -> String { 34 | self.constant_pool.borrow().get_utf8(self.name_index) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ch07_method_invoke/src/classfile/constant_pool/cp_name_and_type.rs: -------------------------------------------------------------------------------- 1 | /// CONSTANT_NameAndType_info { 2 | /// u1 tag; 3 | /// u2 name_index; 4 | /// u2 descriptor_index; 5 | /// } 6 | 7 | use super::{ConstantInfo, ClassReader}; 8 | 9 | #[derive(Default)] 10 | pub struct ConstantNameAndTypeInfo { 11 | name_index: u16, 12 | descriptor_index: u16, 13 | } 14 | 15 | impl ConstantInfo for ConstantNameAndTypeInfo { 16 | fn read_info(&mut self, reader: &mut ClassReader) { 17 | self.name_index = reader.read_u16(); 18 | self.descriptor_index = reader.read_u16(); 19 | } 20 | 21 | fn tag(&self) -> u8 { 22 | super::CONSTANT_NAME_AND_TYPE 23 | } 24 | 25 | fn as_any(&self) -> &dyn std::any::Any { 26 | self 27 | } 28 | } 29 | 30 | impl ConstantNameAndTypeInfo { 31 | pub fn name_index(&self) -> u16 { 32 | self.name_index 33 | } 34 | 35 | pub fn descriptor_index(&self) -> u16 { 36 | self.descriptor_index 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /ch09_native/src/instructions/math/or.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | // Boolean OR int 7 | #[derive(Default, Debug)] 8 | pub struct IOR; 9 | 10 | impl Instruction for IOR { 11 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 12 | let stack = frame.operand_stack_mut(); 13 | let v2 = stack.pop_int(); 14 | let v1 = stack.pop_int(); 15 | let result = v1 | v2; 16 | stack.push_int(result); 17 | 18 | Ok(()) 19 | } 20 | } 21 | 22 | // Boolean OR long 23 | #[derive(Default, Debug)] 24 | pub struct LOR; 25 | 26 | impl Instruction for LOR { 27 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 28 | let stack = frame.operand_stack_mut(); 29 | let v2 = stack.pop_long(); 30 | let v1 = stack.pop_long(); 31 | let result = v1 | v2; 32 | stack.push_long(result); 33 | 34 | Ok(()) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /java/example/src/main/java/jvmrust/ch07/ClinitTest.java: -------------------------------------------------------------------------------- 1 | package jvmrust.ch07; 2 | 3 | public class ClinitTest { 4 | 5 | public static final boolean Z = true; 6 | public static final byte B = 1; 7 | public static final short S = 2; 8 | public static final int I = 3; 9 | public static final long L = 4; 10 | public static final char C = 'x'; 11 | public static final float F = 3.14f; 12 | public static final double D = 2.71828; 13 | public static final String STR = "abc"; 14 | public static boolean z = true; 15 | public static byte b = 1; 16 | public static short s = 2; 17 | public static int i = 3; 18 | public static long l = 4; 19 | public static char c = 'x'; 20 | public static float f = 3.14f; 21 | public static double d = 2.71828; 22 | public static String str = "abc"; 23 | 24 | public static void main(String[] args) { 25 | System.out.println(ClinitTest.I); 26 | System.out.println(ClinitTest.i); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /ch03_classfile/src/classfile/constant_pool/cp_class.rs: -------------------------------------------------------------------------------- 1 | /// CONSTANT_Class_info { 2 | /// u1 tag; 3 | /// u2 name_index; 4 | /// } 5 | 6 | use crate::types::RcRefCell; 7 | use super::{ConstantInfo, ClassReader, ConstantPool}; 8 | 9 | #[derive(Clone)] 10 | pub struct ConstantClassInfo { 11 | constant_pool: RcRefCell, 12 | name_index: u16, 13 | } 14 | 15 | impl ConstantInfo for ConstantClassInfo { 16 | fn read_info(&mut self, reader: &mut ClassReader) { 17 | self.name_index = reader.read_u16(); 18 | } 19 | 20 | fn tag(&self) -> u8 { 21 | super::CONSTANT_CLASS 22 | } 23 | } 24 | 25 | impl ConstantClassInfo { 26 | pub fn new(cp: RcRefCell) -> Self { 27 | ConstantClassInfo { 28 | constant_pool: cp, 29 | name_index: 0, 30 | } 31 | } 32 | 33 | pub fn name(&self) -> String { 34 | self.constant_pool.borrow().get_utf8(self.name_index) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ch05_instructions/src/classfile/constant_pool/cp_class.rs: -------------------------------------------------------------------------------- 1 | /// CONSTANT_Class_info { 2 | /// u1 tag; 3 | /// u2 name_index; 4 | /// } 5 | 6 | use crate::types::RcRefCell; 7 | use super::{ConstantInfo, ClassReader, ConstantPool}; 8 | 9 | #[derive(Clone)] 10 | pub struct ConstantClassInfo { 11 | constant_pool: RcRefCell, 12 | name_index: u16, 13 | } 14 | 15 | impl ConstantInfo for ConstantClassInfo { 16 | fn read_info(&mut self, reader: &mut ClassReader) { 17 | self.name_index = reader.read_u16(); 18 | } 19 | 20 | fn tag(&self) -> u8 { 21 | super::CONSTANT_CLASS 22 | } 23 | } 24 | 25 | impl ConstantClassInfo { 26 | pub fn new(cp: RcRefCell) -> Self { 27 | ConstantClassInfo { 28 | constant_pool: cp, 29 | name_index: 0, 30 | } 31 | } 32 | 33 | pub fn name(&self) -> String { 34 | self.constant_pool.borrow().get_utf8(self.name_index) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ch08_array_string/src/instructions/math/or.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | // Boolean OR int 7 | #[derive(Default, Debug)] 8 | pub struct IOR; 9 | 10 | impl Instruction for IOR { 11 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 12 | let stack = frame.operand_stack_mut(); 13 | let v2 = stack.pop_int(); 14 | let v1 = stack.pop_int(); 15 | let result = v1 | v2; 16 | stack.push_int(result); 17 | 18 | Ok(()) 19 | } 20 | } 21 | 22 | // Boolean OR long 23 | #[derive(Default, Debug)] 24 | pub struct LOR; 25 | 26 | impl Instruction for LOR { 27 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 28 | let stack = frame.operand_stack_mut(); 29 | let v2 = stack.pop_long(); 30 | let v1 = stack.pop_long(); 31 | let result = v1 | v2; 32 | stack.push_long(result); 33 | 34 | Ok(()) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ch09_native/src/instructions/math/xor.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | // Boolean XOR int 7 | #[derive(Default, Debug)] 8 | pub struct IXOR; 9 | 10 | impl Instruction for IXOR { 11 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 12 | let stack = frame.operand_stack_mut(); 13 | let v1 = stack.pop_int(); 14 | let v2 = stack.pop_int(); 15 | let result = v1 ^ v2; 16 | stack.push_int(result); 17 | 18 | Ok(()) 19 | } 20 | } 21 | 22 | // Boolean XOR long 23 | #[derive(Default, Debug)] 24 | pub struct LXOR; 25 | 26 | impl Instruction for LXOR { 27 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 28 | let stack = frame.operand_stack_mut(); 29 | let v1 = stack.pop_long(); 30 | let v2 = stack.pop_long(); 31 | let result = v1 ^ v2; 32 | stack.push_long(result); 33 | 34 | Ok(()) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ch10_exception/src/instructions/math/or.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | // Boolean OR int 7 | #[derive(Default, Debug)] 8 | pub struct IOR; 9 | 10 | impl Instruction for IOR { 11 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 12 | let stack = frame.operand_stack_mut(); 13 | let v2 = stack.pop_int(); 14 | let v1 = stack.pop_int(); 15 | let result = v1 | v2; 16 | stack.push_int(result); 17 | 18 | Ok(()) 19 | } 20 | } 21 | 22 | // Boolean OR long 23 | #[derive(Default, Debug)] 24 | pub struct LOR; 25 | 26 | impl Instruction for LOR { 27 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 28 | let stack = frame.operand_stack_mut(); 29 | let v2 = stack.pop_long(); 30 | let v1 = stack.pop_long(); 31 | let result = v1 | v2; 32 | stack.push_long(result); 33 | 34 | Ok(()) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ch06_rtda_heap/src/instructions/constants/ipush.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | use super::super::bytecode_reader::BytecodeReader; 6 | 7 | /// Push byte 8 | #[derive(Default, Debug)] 9 | pub struct BIPUSH { 10 | val: i8, 11 | } 12 | 13 | impl Instruction for BIPUSH { 14 | fn fetch_operands(&mut self, reader: &mut BytecodeReader) { 15 | self.val = reader.read_i8(); 16 | } 17 | 18 | fn execute(&mut self, frame: &mut Frame) { 19 | frame.operand_stack_mut().push_int(self.val as i32); 20 | } 21 | } 22 | 23 | /// Push short 24 | #[derive(Default, Debug)] 25 | pub struct SIPUSH { 26 | val: i16, 27 | } 28 | 29 | impl Instruction for SIPUSH { 30 | fn fetch_operands(&mut self, reader: &mut BytecodeReader) { 31 | self.val = reader.read_i16(); 32 | } 33 | 34 | fn execute(&mut self, frame: &mut Frame) { 35 | frame.operand_stack_mut().push_int(self.val as i32); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /ch09_native/src/classfile/attribute_info/attr_signature.rs: -------------------------------------------------------------------------------- 1 | /// Signature_attribute { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u2 signature_index; 5 | /// } 6 | 7 | use crate::types::RcRefCell; 8 | use super::ConstantPool; 9 | use super::{AttributeInfo, ClassReader}; 10 | 11 | #[derive(Default)] 12 | pub struct SignatureAttribute { 13 | constant_pool: RcRefCell, 14 | signature_index: u16, 15 | } 16 | 17 | impl AttributeInfo for SignatureAttribute { 18 | fn read_info(&mut self, reader: &mut ClassReader) { 19 | self.signature_index = reader.read_u16(); 20 | } 21 | 22 | fn as_any(&self) -> &dyn std::any::Any { 23 | self 24 | } 25 | } 26 | 27 | impl SignatureAttribute { 28 | pub fn new (cp: RcRefCell) -> Self { 29 | let mut sa = SignatureAttribute::default(); 30 | sa.constant_pool = cp; 31 | sa 32 | } 33 | 34 | fn as_any(&self) -> &dyn std::any::Any { 35 | self 36 | } 37 | } -------------------------------------------------------------------------------- /ch10_exception/src/instructions/math/xor.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | // Boolean XOR int 7 | #[derive(Default, Debug)] 8 | pub struct IXOR; 9 | 10 | impl Instruction for IXOR { 11 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 12 | let stack = frame.operand_stack_mut(); 13 | let v1 = stack.pop_int(); 14 | let v2 = stack.pop_int(); 15 | let result = v1 ^ v2; 16 | stack.push_int(result); 17 | 18 | Ok(()) 19 | } 20 | } 21 | 22 | // Boolean XOR long 23 | #[derive(Default, Debug)] 24 | pub struct LXOR; 25 | 26 | impl Instruction for LXOR { 27 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 28 | let stack = frame.operand_stack_mut(); 29 | let v1 = stack.pop_long(); 30 | let v2 = stack.pop_long(); 31 | let result = v1 ^ v2; 32 | stack.push_long(result); 33 | 34 | Ok(()) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ch04_rtda/src/classfile/attribute_info/attr_enclosing_method.rs: -------------------------------------------------------------------------------- 1 | /// EnclosingMethod_attribute { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u2 class_index; 5 | /// u2 method_index; 6 | /// } 7 | 8 | use crate::types::RcRefCell; 9 | use super::ConstantPool; 10 | use super::{AttributeInfo, ClassReader}; 11 | 12 | #[derive(Default)] 13 | pub struct EnclosingMethodAttribute { 14 | constant_pool: RcRefCell, 15 | class_index: u16, 16 | method_index: u16, 17 | } 18 | 19 | impl AttributeInfo for EnclosingMethodAttribute { 20 | fn read_info(&mut self, reader: &mut ClassReader) { 21 | self.class_index = reader.read_u16(); 22 | self.method_index = reader.read_u16(); 23 | } 24 | } 25 | 26 | impl EnclosingMethodAttribute { 27 | pub fn new (cp: RcRefCell) -> Self { 28 | let mut ema = EnclosingMethodAttribute::default(); 29 | ema.constant_pool = cp; 30 | ema 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ch05_instructions/src/instructions/constants/ipush.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | use super::super::bytecode_reader::BytecodeReader; 6 | 7 | /// Push byte 8 | #[derive(Default, Debug)] 9 | pub struct BIPUSH { 10 | val: i8, 11 | } 12 | 13 | impl Instruction for BIPUSH { 14 | fn fetch_operands(&mut self, reader: &mut BytecodeReader) { 15 | self.val = reader.read_i8(); 16 | } 17 | 18 | fn execute(&mut self, frame: &mut Frame) { 19 | frame.operand_stack_mut().push_int(self.val as i32); 20 | } 21 | } 22 | 23 | /// Push short 24 | #[derive(Default, Debug)] 25 | pub struct SIPUSH { 26 | val: i16, 27 | } 28 | 29 | impl Instruction for SIPUSH { 30 | fn fetch_operands(&mut self, reader: &mut BytecodeReader) { 31 | self.val = reader.read_i16(); 32 | } 33 | 34 | fn execute(&mut self, frame: &mut Frame) { 35 | frame.operand_stack_mut().push_int(self.val as i32); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /ch07_method_invoke/src/instructions/constants/ipush.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | use super::super::bytecode_reader::BytecodeReader; 6 | 7 | /// Push byte 8 | #[derive(Default, Debug)] 9 | pub struct BIPUSH { 10 | val: i8, 11 | } 12 | 13 | impl Instruction for BIPUSH { 14 | fn fetch_operands(&mut self, reader: &mut BytecodeReader) { 15 | self.val = reader.read_i8(); 16 | } 17 | 18 | fn execute(&mut self, frame: &mut Frame) { 19 | frame.operand_stack_mut().push_int(self.val as i32); 20 | } 21 | } 22 | 23 | /// Push short 24 | #[derive(Default, Debug)] 25 | pub struct SIPUSH { 26 | val: i16, 27 | } 28 | 29 | impl Instruction for SIPUSH { 30 | fn fetch_operands(&mut self, reader: &mut BytecodeReader) { 31 | self.val = reader.read_i16(); 32 | } 33 | 34 | fn execute(&mut self, frame: &mut Frame) { 35 | frame.operand_stack_mut().push_int(self.val as i32); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /ch08_array_string/src/instructions/math/xor.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | // Boolean XOR int 7 | #[derive(Default, Debug)] 8 | pub struct IXOR; 9 | 10 | impl Instruction for IXOR { 11 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 12 | let stack = frame.operand_stack_mut(); 13 | let v1 = stack.pop_int(); 14 | let v2 = stack.pop_int(); 15 | let result = v1 ^ v2; 16 | stack.push_int(result); 17 | 18 | Ok(()) 19 | } 20 | } 21 | 22 | // Boolean XOR long 23 | #[derive(Default, Debug)] 24 | pub struct LXOR; 25 | 26 | impl Instruction for LXOR { 27 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 28 | let stack = frame.operand_stack_mut(); 29 | let v1 = stack.pop_long(); 30 | let v2 = stack.pop_long(); 31 | let result = v1 ^ v2; 32 | stack.push_long(result); 33 | 34 | Ok(()) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ch09_native/src/instructions/math/and.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | // Boolean AND int 7 | 8 | #[derive(Default, Debug)] 9 | pub struct IAND; 10 | 11 | impl Instruction for IAND { 12 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 13 | let stack = frame.operand_stack_mut(); 14 | let v2 = stack.pop_int(); 15 | let v1 = stack.pop_int(); 16 | let result = v1 & v2; 17 | stack.push_int(result); 18 | 19 | Ok(()) 20 | } 21 | } 22 | 23 | // Boolean AND long 24 | #[derive(Default, Debug)] 25 | pub struct LAND; 26 | 27 | impl Instruction for LAND { 28 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 29 | let stack = frame.operand_stack_mut(); 30 | let v2 = stack.pop_long(); 31 | let v1 = stack.pop_long(); 32 | let result = v1 & v2; 33 | stack.push_long(result); 34 | 35 | Ok(()) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /ch10_exception/src/classfile/attribute_info/attr_signature.rs: -------------------------------------------------------------------------------- 1 | /// Signature_attribute { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u2 signature_index; 5 | /// } 6 | 7 | use crate::types::RcRefCell; 8 | use super::ConstantPool; 9 | use super::{AttributeInfo, ClassReader}; 10 | 11 | #[derive(Default)] 12 | pub struct SignatureAttribute { 13 | constant_pool: RcRefCell, 14 | signature_index: u16, 15 | } 16 | 17 | impl AttributeInfo for SignatureAttribute { 18 | fn read_info(&mut self, reader: &mut ClassReader) { 19 | self.signature_index = reader.read_u16(); 20 | } 21 | 22 | fn as_any(&self) -> &dyn std::any::Any { 23 | self 24 | } 25 | } 26 | 27 | impl SignatureAttribute { 28 | pub fn new(cp: RcRefCell) -> Self { 29 | let mut sa = SignatureAttribute::default(); 30 | sa.constant_pool = cp; 31 | sa 32 | } 33 | 34 | fn as_any(&self) -> &dyn std::any::Any { 35 | self 36 | } 37 | } -------------------------------------------------------------------------------- /ch10_exception/src/instructions/math/and.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | // Boolean AND int 7 | 8 | #[derive(Default, Debug)] 9 | pub struct IAND; 10 | 11 | impl Instruction for IAND { 12 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 13 | let stack = frame.operand_stack_mut(); 14 | let v2 = stack.pop_int(); 15 | let v1 = stack.pop_int(); 16 | let result = v1 & v2; 17 | stack.push_int(result); 18 | 19 | Ok(()) 20 | } 21 | } 22 | 23 | // Boolean AND long 24 | #[derive(Default, Debug)] 25 | pub struct LAND; 26 | 27 | impl Instruction for LAND { 28 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 29 | let stack = frame.operand_stack_mut(); 30 | let v2 = stack.pop_long(); 31 | let v1 = stack.pop_long(); 32 | let result = v1 & v2; 33 | stack.push_long(result); 34 | 35 | Ok(()) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /ch03_classfile/src/classfile/attribute_info/attr_enclosing_method.rs: -------------------------------------------------------------------------------- 1 | /// EnclosingMethod_attribute { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u2 class_index; 5 | /// u2 method_index; 6 | /// } 7 | 8 | use crate::types::RcRefCell; 9 | use super::ConstantPool; 10 | use super::{AttributeInfo, ClassReader}; 11 | 12 | #[derive(Default)] 13 | pub struct EnclosingMethodAttribute { 14 | constant_pool: RcRefCell, 15 | class_index: u16, 16 | method_index: u16, 17 | } 18 | 19 | impl AttributeInfo for EnclosingMethodAttribute { 20 | fn read_info(&mut self, reader: &mut ClassReader) { 21 | self.class_index = reader.read_u16(); 22 | self.method_index = reader.read_u16(); 23 | } 24 | } 25 | 26 | impl EnclosingMethodAttribute { 27 | pub fn new (cp: RcRefCell) -> Self { 28 | let mut ema = EnclosingMethodAttribute::default(); 29 | ema.constant_pool = cp; 30 | ema 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ch05_instructions/src/rtda/thread.rs: -------------------------------------------------------------------------------- 1 | use crate::types::{ 2 | RcRefCell, 3 | OptionalRcRefCell, 4 | }; 5 | use super::jvm_stack::Stack; 6 | use super::frame::Frame; 7 | 8 | pub struct Thread { 9 | pc: i64, 10 | stack: Stack, 11 | } 12 | 13 | impl Thread { 14 | pub fn new() -> Self { 15 | Thread { pc: 0, stack: Stack::new(1024) } 16 | } 17 | 18 | pub fn pc(&self) -> i64 { 19 | self.pc 20 | } 21 | 22 | pub fn set_pc(&mut self, pc: i64) { 23 | self.pc = pc; 24 | } 25 | 26 | pub fn push_frame(&mut self, frame: Frame) { 27 | self.stack.push(frame); 28 | } 29 | 30 | pub fn pop_frame(&mut self) -> OptionalRcRefCell { 31 | self.stack.pop() 32 | } 33 | 34 | pub fn current_frame(&self) -> RcRefCell { 35 | self.stack.top() 36 | } 37 | 38 | pub fn new_frame(&self, _self: RcRefCell, max_locals: usize, max_stack: usize) -> Frame { 39 | return Frame::new(_self, max_locals, max_stack); 40 | } 41 | } -------------------------------------------------------------------------------- /ch07_method_invoke/src/classfile/attribute_info/attr_signature.rs: -------------------------------------------------------------------------------- 1 | /// Signature_attribute { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u2 signature_index; 5 | /// } 6 | 7 | use crate::types::RcRefCell; 8 | use super::ConstantPool; 9 | use super::{AttributeInfo, ClassReader}; 10 | 11 | #[derive(Default)] 12 | pub struct SignatureAttribute { 13 | constant_pool: RcRefCell, 14 | signature_index: u16, 15 | } 16 | 17 | impl AttributeInfo for SignatureAttribute { 18 | fn read_info(&mut self, reader: &mut ClassReader) { 19 | self.signature_index = reader.read_u16(); 20 | } 21 | 22 | fn as_any(&self) -> &dyn std::any::Any { 23 | self 24 | } 25 | } 26 | 27 | impl SignatureAttribute { 28 | pub fn new (cp: RcRefCell) -> Self { 29 | let mut sa = SignatureAttribute::default(); 30 | sa.constant_pool = cp; 31 | sa 32 | } 33 | 34 | fn as_any(&self) -> &dyn std::any::Any { 35 | self 36 | } 37 | } -------------------------------------------------------------------------------- /ch08_array_string/src/classfile/attribute_info/attr_signature.rs: -------------------------------------------------------------------------------- 1 | /// Signature_attribute { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u2 signature_index; 5 | /// } 6 | 7 | use crate::types::RcRefCell; 8 | use super::ConstantPool; 9 | use super::{AttributeInfo, ClassReader}; 10 | 11 | #[derive(Default)] 12 | pub struct SignatureAttribute { 13 | constant_pool: RcRefCell, 14 | signature_index: u16, 15 | } 16 | 17 | impl AttributeInfo for SignatureAttribute { 18 | fn read_info(&mut self, reader: &mut ClassReader) { 19 | self.signature_index = reader.read_u16(); 20 | } 21 | 22 | fn as_any(&self) -> &dyn std::any::Any { 23 | self 24 | } 25 | } 26 | 27 | impl SignatureAttribute { 28 | pub fn new (cp: RcRefCell) -> Self { 29 | let mut sa = SignatureAttribute::default(); 30 | sa.constant_pool = cp; 31 | sa 32 | } 33 | 34 | fn as_any(&self) -> &dyn std::any::Any { 35 | self 36 | } 37 | } -------------------------------------------------------------------------------- /ch08_array_string/src/instructions/math/and.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | // Boolean AND int 7 | 8 | #[derive(Default, Debug)] 9 | pub struct IAND; 10 | 11 | impl Instruction for IAND { 12 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 13 | let stack = frame.operand_stack_mut(); 14 | let v2 = stack.pop_int(); 15 | let v1 = stack.pop_int(); 16 | let result = v1 & v2; 17 | stack.push_int(result); 18 | 19 | Ok(()) 20 | } 21 | } 22 | 23 | // Boolean AND long 24 | #[derive(Default, Debug)] 25 | pub struct LAND; 26 | 27 | impl Instruction for LAND { 28 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 29 | let stack = frame.operand_stack_mut(); 30 | let v2 = stack.pop_long(); 31 | let v1 = stack.pop_long(); 32 | let result = v1 & v2; 33 | stack.push_long(result); 34 | 35 | Ok(()) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /java/example/src/main/java/jvmrust/ch10/ExceptionTest1.java: -------------------------------------------------------------------------------- 1 | package jvmrust.ch10; 2 | 3 | public class ExceptionTest1 { 4 | 5 | public static void main(String[] args) { 6 | test(0); 7 | test(1); 8 | test(2); 9 | test(3); 10 | } 11 | 12 | private static void test(int x) { 13 | try { 14 | if (x == 0) { 15 | throw new IllegalArgumentException("0!"); 16 | } 17 | if (x == 1) { 18 | throw new RuntimeException("1!"); 19 | } 20 | if (x == 2) { 21 | throw new Exception("2!"); 22 | } 23 | } catch (IllegalArgumentException e) { 24 | System.out.println(e.getMessage()); 25 | } catch (RuntimeException e) { 26 | System.out.println(e.getMessage()); 27 | } catch (Exception e) { 28 | System.out.println(e.getMessage()); 29 | } finally { 30 | System.out.println(x); 31 | } 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /ch06_rtda_heap/src/classfile/constant_pool/cp_name_and_type.rs: -------------------------------------------------------------------------------- 1 | /// CONSTANT_NameAndType_info { 2 | /// u1 tag; 3 | /// u2 name_index; 4 | /// u2 descriptor_index; 5 | /// } 6 | 7 | use super::{ConstantInfo, ClassReader}; 8 | 9 | #[derive(Default)] 10 | pub struct ConstantNameAndTypeInfo { 11 | name_index: u16, 12 | descriptor_index: u16, 13 | } 14 | 15 | impl ConstantInfo for ConstantNameAndTypeInfo { 16 | fn read_info(&mut self, reader: &mut ClassReader) { 17 | self.name_index = reader.read_u16(); 18 | self.descriptor_index = reader.read_u16(); 19 | } 20 | 21 | fn tag(&self) -> u8 { 22 | super::CONSTANT_NAME_AND_TYPE 23 | } 24 | 25 | fn as_any(&self) -> &dyn std::any::Any { 26 | self 27 | } 28 | } 29 | 30 | impl ConstantNameAndTypeInfo { 31 | pub fn name_index(&self) -> u16 { 32 | self.name_index 33 | } 34 | 35 | pub fn descriptor_index(&self) -> u16 { 36 | self.descriptor_index 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /ch06_rtda_heap/src/rtda/thread.rs: -------------------------------------------------------------------------------- 1 | use crate::types::{ 2 | RcRefCell, 3 | OptionalRcRefCell, 4 | }; 5 | use super::jvm_stack::Stack; 6 | use super::frame::Frame; 7 | use super::heap::method::Method; 8 | 9 | pub struct Thread { 10 | pc: i64, 11 | stack: Stack, 12 | } 13 | 14 | impl Thread { 15 | pub fn new() -> Self { 16 | Thread { pc: 0, stack: Stack::new(1024) } 17 | } 18 | 19 | pub fn pc(&self) -> i64 { 20 | self.pc 21 | } 22 | 23 | pub fn set_pc(&mut self, pc: i64) { 24 | self.pc = pc; 25 | } 26 | 27 | pub fn push_frame(&mut self, frame: Frame) { 28 | self.stack.push(frame); 29 | } 30 | 31 | pub fn pop_frame(&mut self) -> OptionalRcRefCell { 32 | self.stack.pop() 33 | } 34 | 35 | pub fn current_frame(&self) -> RcRefCell { 36 | self.stack.top() 37 | } 38 | 39 | pub fn new_frame(&self, _self: RcRefCell, method: RcRefCell) -> Frame { 40 | return Frame::new(_self, method); 41 | } 42 | } -------------------------------------------------------------------------------- /ch06_rtda_heap/src/classfile/attribute_info/attr_signature.rs: -------------------------------------------------------------------------------- 1 | /// Signature_attribute { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u2 signature_index; 5 | /// } 6 | 7 | use crate::types::RcRefCell; 8 | use super::ConstantPool; 9 | use super::{AttributeInfo, ClassReader}; 10 | 11 | #[derive(Default)] 12 | pub struct SignatureAttribute { 13 | constant_pool: RcRefCell, 14 | signature_index: u16, 15 | } 16 | 17 | impl AttributeInfo for SignatureAttribute { 18 | fn read_info(&mut self, reader: &mut ClassReader) { 19 | self.signature_index = reader.read_u16(); 20 | } 21 | 22 | fn as_any(&self) -> &dyn std::any::Any { 23 | self 24 | } 25 | } 26 | 27 | impl SignatureAttribute { 28 | pub fn new (cp: RcRefCell) -> Self { 29 | let mut sa = SignatureAttribute::default(); 30 | sa.constant_pool = cp; 31 | sa 32 | } 33 | 34 | fn as_any(&self) -> &dyn std::any::Any { 35 | self 36 | } 37 | } -------------------------------------------------------------------------------- /ch09_native/src/classfile/constant_pool/cp_class.rs: -------------------------------------------------------------------------------- 1 | /// CONSTANT_Class_info { 2 | /// u1 tag; 3 | /// u2 name_index; 4 | /// } 5 | 6 | use crate::types::RcRefCell; 7 | use super::{ConstantInfo, ClassReader, ConstantPool}; 8 | 9 | #[derive(Clone)] 10 | pub struct ConstantClassInfo { 11 | constant_pool: RcRefCell, 12 | name_index: u16, 13 | } 14 | 15 | impl ConstantInfo for ConstantClassInfo { 16 | fn read_info(&mut self, reader: &mut ClassReader) { 17 | self.name_index = reader.read_u16(); 18 | } 19 | 20 | fn tag(&self) -> u8 { 21 | super::CONSTANT_CLASS 22 | } 23 | 24 | fn as_any(&self) -> &dyn std::any::Any { 25 | self 26 | } 27 | } 28 | 29 | impl ConstantClassInfo { 30 | pub fn new(cp: RcRefCell) -> Self { 31 | ConstantClassInfo { 32 | constant_pool: cp, 33 | name_index: 0, 34 | } 35 | } 36 | 37 | pub fn name(&self) -> String { 38 | self.constant_pool.borrow().get_utf8(self.name_index) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ch05_instructions/src/classfile/attribute_info/attr_signature.rs: -------------------------------------------------------------------------------- 1 | /// Signature_attribute { 2 | /// u2 attribute_name_index; 3 | /// u4 attribute_length; 4 | /// u2 signature_index; 5 | /// } 6 | 7 | use crate::types::RcRefCell; 8 | use super::ConstantPool; 9 | use super::{AttributeInfo, ClassReader}; 10 | 11 | #[derive(Default)] 12 | pub struct SignatureAttribute { 13 | constant_pool: RcRefCell, 14 | signature_index: u16, 15 | } 16 | 17 | impl AttributeInfo for SignatureAttribute { 18 | fn read_info(&mut self, reader: &mut ClassReader) { 19 | self.signature_index = reader.read_u16(); 20 | } 21 | 22 | fn as_any(&self) -> &dyn std::any::Any { 23 | self 24 | } 25 | } 26 | 27 | impl SignatureAttribute { 28 | pub fn new (cp: RcRefCell) -> Self { 29 | let mut sa = SignatureAttribute::default(); 30 | sa.constant_pool = cp; 31 | sa 32 | } 33 | 34 | fn as_any(&self) -> &dyn std::any::Any { 35 | self 36 | } 37 | } -------------------------------------------------------------------------------- /ch07_method_invoke/src/classfile/constant_pool/cp_class.rs: -------------------------------------------------------------------------------- 1 | /// CONSTANT_Class_info { 2 | /// u1 tag; 3 | /// u2 name_index; 4 | /// } 5 | 6 | use crate::types::RcRefCell; 7 | use super::{ConstantInfo, ClassReader, ConstantPool}; 8 | 9 | #[derive(Clone)] 10 | pub struct ConstantClassInfo { 11 | constant_pool: RcRefCell, 12 | name_index: u16, 13 | } 14 | 15 | impl ConstantInfo for ConstantClassInfo { 16 | fn read_info(&mut self, reader: &mut ClassReader) { 17 | self.name_index = reader.read_u16(); 18 | } 19 | 20 | fn tag(&self) -> u8 { 21 | super::CONSTANT_CLASS 22 | } 23 | 24 | fn as_any(&self) -> &dyn std::any::Any { 25 | self 26 | } 27 | } 28 | 29 | impl ConstantClassInfo { 30 | pub fn new(cp: RcRefCell) -> Self { 31 | ConstantClassInfo { 32 | constant_pool: cp, 33 | name_index: 0, 34 | } 35 | } 36 | 37 | pub fn name(&self) -> String { 38 | self.constant_pool.borrow().get_utf8(self.name_index) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ch08_array_string/src/classfile/constant_pool/cp_class.rs: -------------------------------------------------------------------------------- 1 | /// CONSTANT_Class_info { 2 | /// u1 tag; 3 | /// u2 name_index; 4 | /// } 5 | 6 | use crate::types::RcRefCell; 7 | use super::{ConstantInfo, ClassReader, ConstantPool}; 8 | 9 | #[derive(Clone)] 10 | pub struct ConstantClassInfo { 11 | constant_pool: RcRefCell, 12 | name_index: u16, 13 | } 14 | 15 | impl ConstantInfo for ConstantClassInfo { 16 | fn read_info(&mut self, reader: &mut ClassReader) { 17 | self.name_index = reader.read_u16(); 18 | } 19 | 20 | fn tag(&self) -> u8 { 21 | super::CONSTANT_CLASS 22 | } 23 | 24 | fn as_any(&self) -> &dyn std::any::Any { 25 | self 26 | } 27 | } 28 | 29 | impl ConstantClassInfo { 30 | pub fn new(cp: RcRefCell) -> Self { 31 | ConstantClassInfo { 32 | constant_pool: cp, 33 | name_index: 0, 34 | } 35 | } 36 | 37 | pub fn name(&self) -> String { 38 | self.constant_pool.borrow().get_utf8(self.name_index) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ch09_native/src/classfile/constant_pool/cp_string.rs: -------------------------------------------------------------------------------- 1 | /// CONSTANT_String_info { 2 | /// u1 tag; 3 | /// u2 string_index; 4 | /// } 5 | 6 | use crate::types::RcRefCell; 7 | use super::{ConstantInfo, ClassReader, ConstantPool}; 8 | 9 | pub struct ConstantStringInfo { 10 | constant_pool: RcRefCell, 11 | string_index: u16 12 | } 13 | 14 | impl ConstantInfo for ConstantStringInfo { 15 | fn read_info(&mut self, reader: &mut ClassReader) { 16 | self.string_index = reader.read_u16(); 17 | } 18 | 19 | fn tag(&self) -> u8 { 20 | super::CONSTANT_STRING 21 | } 22 | 23 | fn as_any(&self) -> &dyn std::any::Any { 24 | self 25 | } 26 | 27 | } 28 | 29 | impl ConstantStringInfo { 30 | pub fn new(cp: RcRefCell) -> Self { 31 | ConstantStringInfo { 32 | constant_pool: cp, 33 | string_index: 0, 34 | } 35 | } 36 | 37 | pub fn to_string(&self) -> String { 38 | self.constant_pool.borrow().get_utf8(self.string_index) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ch10_exception/src/classfile/constant_pool/cp_class.rs: -------------------------------------------------------------------------------- 1 | /// CONSTANT_Class_info { 2 | /// u1 tag; 3 | /// u2 name_index; 4 | /// } 5 | 6 | use crate::types::RcRefCell; 7 | use super::{ConstantInfo, ClassReader, ConstantPool}; 8 | 9 | #[derive(Clone)] 10 | pub struct ConstantClassInfo { 11 | constant_pool: RcRefCell, 12 | name_index: u16, 13 | } 14 | 15 | impl ConstantInfo for ConstantClassInfo { 16 | fn read_info(&mut self, reader: &mut ClassReader) { 17 | self.name_index = reader.read_u16(); 18 | } 19 | 20 | fn tag(&self) -> u8 { 21 | super::CONSTANT_CLASS 22 | } 23 | 24 | fn as_any(&self) -> &dyn std::any::Any { 25 | self 26 | } 27 | } 28 | 29 | impl ConstantClassInfo { 30 | pub fn new(cp: RcRefCell) -> Self { 31 | ConstantClassInfo { 32 | constant_pool: cp, 33 | name_index: 0, 34 | } 35 | } 36 | 37 | pub fn name(&self) -> String { 38 | self.constant_pool.borrow().get_utf8(self.name_index) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ch07_method_invoke/src/classfile/constant_pool/cp_string.rs: -------------------------------------------------------------------------------- 1 | /// CONSTANT_String_info { 2 | /// u1 tag; 3 | /// u2 string_index; 4 | /// } 5 | 6 | use crate::types::RcRefCell; 7 | use super::{ConstantInfo, ClassReader, ConstantPool}; 8 | 9 | pub struct ConstantStringInfo { 10 | constant_pool: RcRefCell, 11 | string_index: u16 12 | } 13 | 14 | impl ConstantInfo for ConstantStringInfo { 15 | fn read_info(&mut self, reader: &mut ClassReader) { 16 | self.string_index = reader.read_u16(); 17 | } 18 | 19 | fn tag(&self) -> u8 { 20 | super::CONSTANT_STRING 21 | } 22 | 23 | fn as_any(&self) -> &dyn std::any::Any { 24 | self 25 | } 26 | 27 | } 28 | 29 | impl ConstantStringInfo { 30 | pub fn new(cp: RcRefCell) -> Self { 31 | ConstantStringInfo { 32 | constant_pool: cp, 33 | string_index: 0, 34 | } 35 | } 36 | 37 | pub fn to_string(&self) -> String { 38 | self.constant_pool.borrow().get_utf8(self.string_index) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ch08_array_string/src/classfile/constant_pool/cp_string.rs: -------------------------------------------------------------------------------- 1 | /// CONSTANT_String_info { 2 | /// u1 tag; 3 | /// u2 string_index; 4 | /// } 5 | 6 | use crate::types::RcRefCell; 7 | use super::{ConstantInfo, ClassReader, ConstantPool}; 8 | 9 | pub struct ConstantStringInfo { 10 | constant_pool: RcRefCell, 11 | string_index: u16 12 | } 13 | 14 | impl ConstantInfo for ConstantStringInfo { 15 | fn read_info(&mut self, reader: &mut ClassReader) { 16 | self.string_index = reader.read_u16(); 17 | } 18 | 19 | fn tag(&self) -> u8 { 20 | super::CONSTANT_STRING 21 | } 22 | 23 | fn as_any(&self) -> &dyn std::any::Any { 24 | self 25 | } 26 | 27 | } 28 | 29 | impl ConstantStringInfo { 30 | pub fn new(cp: RcRefCell) -> Self { 31 | ConstantStringInfo { 32 | constant_pool: cp, 33 | string_index: 0, 34 | } 35 | } 36 | 37 | pub fn to_string(&self) -> String { 38 | self.constant_pool.borrow().get_utf8(self.string_index) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ch10_exception/src/classfile/constant_pool/cp_string.rs: -------------------------------------------------------------------------------- 1 | /// CONSTANT_String_info { 2 | /// u1 tag; 3 | /// u2 string_index; 4 | /// } 5 | 6 | use crate::types::RcRefCell; 7 | use super::{ConstantInfo, ClassReader, ConstantPool}; 8 | 9 | pub struct ConstantStringInfo { 10 | constant_pool: RcRefCell, 11 | string_index: u16 12 | } 13 | 14 | impl ConstantInfo for ConstantStringInfo { 15 | fn read_info(&mut self, reader: &mut ClassReader) { 16 | self.string_index = reader.read_u16(); 17 | } 18 | 19 | fn tag(&self) -> u8 { 20 | super::CONSTANT_STRING 21 | } 22 | 23 | fn as_any(&self) -> &dyn std::any::Any { 24 | self 25 | } 26 | 27 | } 28 | 29 | impl ConstantStringInfo { 30 | pub fn new(cp: RcRefCell) -> Self { 31 | ConstantStringInfo { 32 | constant_pool: cp, 33 | string_index: 0, 34 | } 35 | } 36 | 37 | pub fn to_string(&self) -> String { 38 | self.constant_pool.borrow().get_utf8(self.string_index) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ch09_native/src/instructions/comparisons/dcmp.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | /// Compare double 7 | #[derive(Default, Debug)] 8 | pub struct DCMPG; 9 | 10 | impl Instruction for DCMPG { 11 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 12 | _dcmp(frame, true); 13 | 14 | Ok(()) 15 | } 16 | } 17 | 18 | #[derive(Default, Debug)] 19 | pub struct DCMPL; 20 | 21 | impl Instruction for DCMPL { 22 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 23 | _dcmp(frame, false); 24 | 25 | Ok(()) 26 | } 27 | } 28 | 29 | fn _dcmp(frame: &mut Frame, g_flag: bool) { 30 | let stack = frame.operand_stack_mut(); 31 | let v2 = stack.pop_double(); 32 | let v1 = stack.pop_double(); 33 | if v1 > v2 { 34 | stack.push_int(1); 35 | } else if v1 == v2 { 36 | stack.push_int(0); 37 | } else if v1 < v2 { 38 | stack.push_int(-1); 39 | } else if g_flag { 40 | stack.push_int(1); 41 | } else { 42 | stack.push_int(-1); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /ch09_native/src/instructions/comparisons/fcmp.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | /// Compare float 7 | #[derive(Default, Debug)] 8 | pub struct FCMPG; 9 | 10 | impl Instruction for FCMPG { 11 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 12 | _fcmp(frame, true); 13 | 14 | Ok(()) 15 | } 16 | } 17 | 18 | #[derive(Default, Debug)] 19 | pub struct FCMPL; 20 | 21 | impl Instruction for FCMPL { 22 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 23 | _fcmp(frame, false); 24 | 25 | Ok(()) 26 | } 27 | } 28 | 29 | fn _fcmp(frame: &mut Frame, g_flag: bool) { 30 | let stack = frame.operand_stack_mut(); 31 | let v2 = stack.pop_float(); 32 | let v1 = stack.pop_float(); 33 | if v1 > v2 { 34 | stack.push_int(1); 35 | } else if v1 == v2 { 36 | stack.push_int(0); 37 | } else if v1 < v2 { 38 | stack.push_int(-1); 39 | } else if g_flag { 40 | stack.push_int(1); 41 | } else { 42 | stack.push_int(-1); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /ch10_exception/src/instructions/comparisons/fcmp.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | /// Compare float 7 | #[derive(Default, Debug)] 8 | pub struct FCMPG; 9 | 10 | impl Instruction for FCMPG { 11 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 12 | _fcmp(frame, true); 13 | 14 | Ok(()) 15 | } 16 | } 17 | 18 | #[derive(Default, Debug)] 19 | pub struct FCMPL; 20 | 21 | impl Instruction for FCMPL { 22 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 23 | _fcmp(frame, false); 24 | 25 | Ok(()) 26 | } 27 | } 28 | 29 | fn _fcmp(frame: &mut Frame, g_flag: bool) { 30 | let stack = frame.operand_stack_mut(); 31 | let v2 = stack.pop_float(); 32 | let v1 = stack.pop_float(); 33 | if v1 > v2 { 34 | stack.push_int(1); 35 | } else if v1 == v2 { 36 | stack.push_int(0); 37 | } else if v1 < v2 { 38 | stack.push_int(-1); 39 | } else if g_flag { 40 | stack.push_int(1); 41 | } else { 42 | stack.push_int(-1); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /ch08_array_string/src/instructions/comparisons/dcmp.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use crate::rtda::Frame; 4 | use super::super::instruction::Instruction; 5 | 6 | /// Compare double 7 | #[derive(Default, Debug)] 8 | pub struct DCMPG; 9 | 10 | impl Instruction for DCMPG { 11 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 12 | _dcmp(frame, true); 13 | 14 | Ok(()) 15 | } 16 | } 17 | 18 | #[derive(Default, Debug)] 19 | pub struct DCMPL; 20 | 21 | impl Instruction for DCMPL { 22 | fn execute(&mut self, frame: &mut Frame) -> crate::Result<()> { 23 | _dcmp(frame, false); 24 | 25 | Ok(()) 26 | } 27 | } 28 | 29 | fn _dcmp(frame: &mut Frame, g_flag: bool) { 30 | let stack = frame.operand_stack_mut(); 31 | let v2 = stack.pop_double(); 32 | let v1 = stack.pop_double(); 33 | if v1 > v2 { 34 | stack.push_int(1); 35 | } else if v1 == v2 { 36 | stack.push_int(0); 37 | } else if v1 < v2 { 38 | stack.push_int(-1); 39 | } else if g_flag { 40 | stack.push_int(1); 41 | } else { 42 | stack.push_int(-1); 43 | } 44 | } 45 | --------------------------------------------------------------------------------