[
  {
    "path": ".gitignore",
    "content": "/target\n**/*.rs.bk\n*.class\n.idea\n"
  },
  {
    "path": "Cargo.toml",
    "content": "[workspace]\nmembers = [\n  \"jvm\",\n  \"libjvm\",\n  \"crates/classfile\",\n  \"crates/class-parser\",\n  \"crates/vm\",\n  \"tools/javap\"\n]\n\n#https://doc.rust-lang.org/cargo/reference/profiles.html\n[profile.release]\nlto = \"fat\"\ncodegen-units = 1\npanic = \"abort\"\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2021 douchuan and other contributors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "Have a great goal is a very important thing, such as Moon Landing.\nWhat is the meaning of this plan? \nThat's the process of achieving this goal, the produce of industry and technology.\n\nSun is a great company, in the era of C++, they created JVM & HotSpot.\n\nNow, we have Rust, a better tool, let’s remake JVM! \n\nPay tribute to medical workers at the front! Thank you for your contribution to the fight against the epidemic.\n\n\n## Roadmap\n\n- Pass test cases in JDK \n- Pass TCK \n- GC (crate)\n- JIT / interp (crate)\n- class verification (crate)\n- After GC built, ready for optimize System.arraycopy (the key of performance)\n- WebAssembly, make the JVM work in Browser \n- java options (-version, -server...)\n\nIn summary, the roadmap is built on a 3-step progress.\n- Pass TCK\n- Refactor & Rewrite\n- Divide into several crates, build a collection of modular and reusable vm technologies\n\nWell, it's a long term plan, Sun spent 30 years to improve\nVM, Oracle continue doing it.\n\nThe journey of a thousand miles begins with one first step. Even the sage was once an ordinary human being.\n\nJust Do It.\n\n## Running\n```shell\n# setup JDK\n# setup rust toolchain\n# clone this project\n\n# compile sample by javac\ncd jvm/sample\njavac HelloWorld.java\ncd ..\n\n# modify r.sh JAVA_HOME according to your env\n# exec sample\ncd jvm\nbash r.sh\n```"
  },
  {
    "path": "crates/class-parser/Cargo.toml",
    "content": "[package]\nname = \"class-parser\"\nversion = \"0.1.0\"\nauthors = [\"Dou Chuan <1843657913@qq.com>\"]\nedition = \"2018\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\nclassfile = { path = \"../classfile\", version = \"0.1.0\" }\nnom = \"5.1.1\"\n"
  },
  {
    "path": "crates/class-parser/README.md",
    "content": "## JVM class parser\nThis is the `class-parser` crate, which contains parser\nof `.class`. \n\nThe binary format parser based on \n[`nom`](https://crates.io/crates/nom)."
  },
  {
    "path": "crates/class-parser/src/class.rs",
    "content": "use classfile::{\n    attributes::{self, Tag as AttrTag, TargetInfo, TypeAnnotation},\n    constant_pool, AttributeType, ClassFile, ConstantPool, FieldInfo, MethodInfo, Version,\n};\nuse std::sync::Arc;\n\nuse nom::{\n    call, count, do_parse, named, named_args,\n    number::streaming::{be_u16, be_u32, be_u8},\n    peek, switch, tag, take, value,\n};\n\nnamed!(\n    version<Version>,\n    do_parse!(minor: be_u16 >> major: be_u16 >> (Version { minor, major }))\n);\n\nnamed!(\n    constant_tag<constant_pool::Tag>,\n    do_parse!(tag: be_u8 >> (constant_pool::Tag::from(tag)))\n);\n\n// Const generics still not in stable,\n// idk how to write this fancier without them D:\n// Hope compiler will rewrite this properly\nmacro_rules! gen_take_exact {\n    ($count: expr, $name: ident) => {\n        fn $name(input: &[u8]) -> nom::IResult<&[u8], [u8; $count]> {\n            let mut output = [0; $count];\n            // TODO: Nom error\n            assert!(input.len() >= $count);\n            for i in 0..$count {\n                output[i] = input[i];\n            }\n            Ok((&input[$count..], output))\n        }\n    };\n}\n\ngen_take_exact!(4, take_exact_4);\ngen_take_exact!(8, take_exact_8);\n\nnamed!(\n    cp_entry<constant_pool::Type>,\n    do_parse!(\n        ct: constant_tag\n            >> entry:\n                switch!(value!(ct),\n                    constant_pool::Tag::Class => do_parse!(\n                        name_index: be_u16 >>\n                        (constant_pool::Type::Class { name_index })\n                    ) |\n                    constant_pool::Tag::FieldRef => do_parse!(\n                        class_index: be_u16 >>\n                        name_and_type_index: be_u16 >>\n                        (constant_pool::Type::FieldRef { class_index, name_and_type_index })\n                    ) |\n                    constant_pool::Tag::MethodRef => do_parse!(\n                        class_index: be_u16 >>\n                        name_and_type_index: be_u16 >>\n                        (constant_pool::Type::MethodRef { class_index, name_and_type_index })\n                    ) |\n                    constant_pool::Tag::InterfaceMethodRef => do_parse!(\n                        class_index: be_u16 >>\n                        name_and_type_index: be_u16 >>\n                        (constant_pool::Type::InterfaceMethodRef { class_index, name_and_type_index })\n                    ) |\n                    constant_pool::Tag::String => do_parse!(\n                        string_index: be_u16 >>\n                        (constant_pool::Type::String { string_index })\n                    ) |\n                    constant_pool::Tag::Integer => do_parse!(\n                        v: take_exact_4 >>\n                        (constant_pool::Type::Integer { v })\n                    ) |\n                    constant_pool::Tag::Float => do_parse!(\n                        v: take_exact_4 >>\n                        (constant_pool::Type::Float { v })\n                    ) |\n                    constant_pool::Tag::Long => do_parse!(\n                        v: take_exact_8 >>\n                        (constant_pool::Type::Long { v })\n                    ) |\n                    constant_pool::Tag::Double => do_parse!(\n                        v: take_exact_8 >>\n                        (constant_pool::Type::Double { v })\n                    ) |\n                    constant_pool::Tag::NameAndType => do_parse!(\n                        name_index: be_u16 >>\n                        desc_index: be_u16 >>\n                        (constant_pool::Type::NameAndType { name_index, desc_index })\n                    ) |\n                    constant_pool::Tag::Utf8 => do_parse!(\n                        length: be_u16 >>\n                        bytes: take!(length) >>\n                        (constant_pool::Type::Utf8 { bytes: Arc::new(Vec::from(bytes)) })\n                    ) |\n                    constant_pool::Tag::MethodHandle => do_parse!(\n                        ref_kind: be_u8 >>\n                        ref_index: be_u16 >>\n                        (constant_pool::Type::MethodHandle { ref_kind, ref_index })\n                    ) |\n                    constant_pool::Tag::MethodType => do_parse!(\n                        desc_index: be_u16 >>\n                        (constant_pool::Type::MethodType { desc_index })\n                    ) |\n                    constant_pool::Tag::InvokeDynamic => do_parse!(\n                        bootstrap_method_attr_index: be_u16 >>\n                        name_and_type_index: be_u16 >>\n                        (constant_pool::Type::InvokeDynamic { bootstrap_method_attr_index, name_and_type_index })\n                    )\n                )\n            >> (entry)\n    )\n);\n\nfn constant_pool(input: &[u8]) -> nom::IResult<&[u8], ConstantPool> {\n    let (mut input, count) = be_u16(input)?;\n\n    let mut output = Vec::with_capacity(count as usize);\n    output.push(constant_pool::Type::Nop);\n\n    let mut i = 1;\n    while i < count {\n        let (new_input, constant_type) = cp_entry(input)?;\n        input = new_input;\n\n        i += 1;\n        output.push(constant_type.clone());\n\n        //spec 4.4.5\n        match constant_type {\n            constant_pool::Type::Long { .. } | constant_pool::Type::Double { .. } => {\n                i += 1;\n                output.push(constant_pool::Type::Nop);\n            }\n            _ => (),\n        }\n    }\n\n    Ok((input, Arc::new(output)))\n}\n\nuse attributes::VerificationTypeInfo;\nnamed!(\n    verification_type_info<VerificationTypeInfo>,\n    do_parse!(\n        id: be_u8\n            >> inner:\n                switch!(value!(id),\n                    0 => value!(VerificationTypeInfo::Top) |\n                    1 => value!(VerificationTypeInfo::Integer) |\n                    2 => value!(VerificationTypeInfo::Float) |\n                    3 => value!(VerificationTypeInfo::Long) |\n                    4 => value!(VerificationTypeInfo::Double) |\n                    5 => value!(VerificationTypeInfo::Null) |\n                    6 => value!(VerificationTypeInfo::UninitializedThis) |\n                    7 => do_parse!(\n                        cpool_index: be_u16 >>\n                        (VerificationTypeInfo::Object {cpool_index})\n                    ) |\n                    8 => do_parse!(\n                        offset: be_u16 >>\n                        (VerificationTypeInfo::Uninitialized {offset})\n                    )\n                )\n            >> (inner)\n    )\n);\n\nnamed!(\n    stack_map_frame<attributes::StackMapFrame>,\n    do_parse!(\n        frame_type: be_u8\n            >> inner:\n                switch!(value!(frame_type),\n                    0..=63 => value!(attributes::StackMapFrame::Same {tag: frame_type, offset_delta: frame_type as u16}) |\n                    64..=127 => do_parse!(\n                        offset_delta: value!((frame_type-64) as u16) >>\n                        type_info: verification_type_info >>\n                        (attributes::StackMapFrame::SameLocals1StackItem {\n                            tag: frame_type,\n                            offset_delta,\n                            stack: [type_info],\n                        })\n                    ) |\n                    128..=246 => value!(attributes::StackMapFrame::Reserved(frame_type)) |\n                    247 => do_parse!(\n                        offset_delta: be_u16 >>\n                        type_info: verification_type_info >>\n                        (attributes::StackMapFrame::SameLocals1StackItem {\n                            tag: frame_type,\n                            offset_delta,\n                            stack: [type_info],\n                        })\n                    ) |\n                    248..=250 => do_parse!(\n                        offset_delta: be_u16 >>\n                        (attributes::StackMapFrame::Chop {\n                            tag: frame_type,\n                            offset_delta,\n                        })\n                    ) |\n                    251 => do_parse!(\n                        offset_delta: be_u16 >>\n                        (attributes::StackMapFrame::SameExtended {\n                            tag: frame_type,\n                            offset_delta\n                        })\n                    ) |\n                    252..=254 => do_parse!(\n                        offset_delta: be_u16 >>\n                        locals_count: value!(frame_type - 251) >>\n                        locals: count!(verification_type_info, locals_count as usize) >>\n                        (attributes::StackMapFrame::Append {\n                            tag: frame_type,\n                            offset_delta,\n                            locals,\n                        })\n                    ) |\n                    255 => do_parse!(\n                        offset_delta: be_u16 >>\n                        locals_count: be_u16 >>\n                        locals: count!(verification_type_info, locals_count as usize) >>\n                        stack_count: be_u16 >>\n                        stack: count!(verification_type_info, stack_count as usize) >>\n                        (attributes::StackMapFrame::Full {\n                            tag: frame_type,\n                            offset_delta,\n                            locals,\n                            stack,\n                        })\n                    )\n                )\n            >> (inner)\n    )\n);\n\nnamed!(\n    inner_class<attributes::InnerClass>,\n    do_parse!(\n        inner_class_info_index: be_u16\n            >> outer_class_info_index: be_u16\n            >> inner_name_index: be_u16\n            >> inner_class_access_flags: be_u16\n            >> (attributes::InnerClass {\n                inner_class_info_index,\n                outer_class_info_index,\n                inner_name_index,\n                inner_class_access_flags,\n            })\n    )\n);\n\nnamed!(\n    enclosing_method<attributes::EnclosingMethod>,\n    do_parse!(\n        class_index: be_u16\n            >> method_index: be_u16\n            >> (attributes::EnclosingMethod {\n                class_index,\n                method_index,\n            })\n    )\n);\n\nnamed!(\n    line_number<attributes::LineNumber>,\n    do_parse!(start_pc: be_u16 >> number: be_u16 >> (attributes::LineNumber { start_pc, number }))\n);\n\nnamed!(\n    local_variable<attributes::LocalVariable>,\n    do_parse!(\n        start_pc: be_u16\n            >> length: be_u16\n            >> name_index: be_u16\n            >> signature_index: be_u16\n            >> index: be_u16\n            >> (attributes::LocalVariable {\n                start_pc,\n                length,\n                name_index,\n                signature_index,\n                index,\n            })\n    )\n);\n\nnamed!(\n    element_value_tag<attributes::ElementValueTag>,\n    do_parse!(tag: be_u8 >> (attributes::ElementValueTag::from(tag)))\n);\n\nuse attributes::{ElementValueTag, ElementValueType};\n\n// I didn't found a way to turn byte/char/double/float/... boilerplate into a macro(\nnamed_args!(element_value_type(cp: ConstantPool)<attributes::ElementValueType>, do_parse!(\n    tag: element_value_tag >>\n    inner: switch!(value!(tag),\n        ElementValueTag::Byte => do_parse!(\n            val_index: be_u16 >>\n            (ElementValueType::Byte {val_index})\n        ) |\n        ElementValueTag::Char => do_parse!(\n            val_index: be_u16 >>\n            (ElementValueType::Char {val_index})\n        ) |\n        ElementValueTag::Double => do_parse!(\n            val_index: be_u16 >>\n            (ElementValueType::Double {val_index})\n        ) |\n        ElementValueTag::Float => do_parse!(\n            val_index: be_u16 >>\n            (ElementValueType::Float {val_index})\n        ) |\n        ElementValueTag::Byte => do_parse!(\n            val_index: be_u16 >>\n            (ElementValueType::Byte {val_index})\n        ) |\n        ElementValueTag::Int => do_parse!(\n            val_index: be_u16 >>\n            (ElementValueType::Int {val_index})\n        ) |\n        ElementValueTag::Long => do_parse!(\n            val_index: be_u16 >>\n            (ElementValueType::Long {val_index})\n        ) |\n        ElementValueTag::Short => do_parse!(\n            val_index: be_u16 >>\n            (ElementValueType::Short {val_index})\n        ) |\n        ElementValueTag::Boolean => do_parse!(\n            val_index: be_u16 >>\n            (ElementValueType::Boolean {val_index})\n        ) |\n        ElementValueTag::String => do_parse!(\n            val_index: be_u16 >>\n            (ElementValueType::String {val_index})\n        ) |\n        ElementValueTag::Enum => do_parse!(\n            type_index: be_u16 >>\n            val_index: be_u16 >>\n            (ElementValueType::Enum {type_index, val_index})\n        ) |\n        ElementValueTag::Class => do_parse!(\n            index: be_u16 >>\n            (ElementValueType::Class {index})\n        ) |\n        ElementValueTag::Annotation => do_parse!(\n            value: call!(annotation_entry, cp) >>\n            (ElementValueType::Annotation(attributes::AnnotationElementValue {value}))\n        ) |\n        ElementValueTag::Array => do_parse!(\n            array_size: be_u16 >>\n            values: count!(call!(element_value_type, cp.clone()), array_size as usize) >>\n            (ElementValueType::Array {\n                values,\n            })\n        ) |\n        ElementValueTag::Unknown => value!(ElementValueType::Unknown)\n    ) >>\n    (inner)\n));\n\nnamed_args!(element_value_pair(cp: ConstantPool)<attributes::ElementValuePair>, do_parse!(\n    name_index: be_u16 >>\n    value: call!(element_value_type, cp) >>\n    (attributes::ElementValuePair {name_index, value})\n));\n\nnamed_args!(annotation_entry(cp: ConstantPool)<attributes::AnnotationEntry>, do_parse!(\n    type_index: be_u16 >>\n    pair_count: be_u16 >>\n    pairs: count!(call!(element_value_pair, cp.clone()), pair_count as usize) >>\n    type_name: value!(constant_pool::get_utf8(&cp, type_index as usize).clone()) >>\n    (attributes::AnnotationEntry {type_name, pairs})\n));\n\nnamed!(\n    local_var_target_table<attributes::LocalVarTargetTable>,\n    do_parse!(\n        start_pc: be_u16\n            >> length: be_u16\n            >> index: be_u16\n            >> (attributes::LocalVarTargetTable {\n                start_pc,\n                length,\n                index\n            })\n    )\n);\n\nnamed!(\n    target_info<TargetInfo>,\n    do_parse!(\n        target_type: be_u8\n            >> inner:\n                switch!(value!(target_type),\n                    0x00 | 0x01 => do_parse!(\n                        type_parameter_index: be_u8 >>\n                        (TargetInfo::TypeParameter { type_parameter_index })\n                    ) |\n                    0x10 => do_parse!(\n                        supertype_index: be_u16 >>\n                        (TargetInfo::SuperType { supertype_index })\n                    ) |\n                    0x11 | 0x12 => do_parse!(\n                        type_parameter_index: be_u8 >>\n                        bound_index: be_u8 >>\n                        (TargetInfo::TypeParameterBound {type_parameter_index, bound_index})\n                    ) |\n                    0x13 | 0x14 | 0x15 => value!(TargetInfo::Empty) |\n                    0x16 => do_parse!(\n                        formal_parameter_index: be_u8 >>\n                        (TargetInfo::FormalParameter {formal_parameter_index})\n                    ) |\n                    0x17 => do_parse!(\n                        throws_type_index: be_u16 >>\n                        (TargetInfo::Throws {throws_type_index})\n                    ) |\n                    0x40 | 0x41 => do_parse!(\n                        item_count: be_u16 >>\n                        items: count!(local_var_target_table, item_count as usize) >>\n                        (TargetInfo::LocalVar {table: items})\n                    ) |\n                    0x42 => do_parse!(\n                        exception_table_index: be_u16 >>\n                        (TargetInfo::Catch {exception_table_index})\n                    ) |\n                    0x43 | 0x44 | 0x45 | 0x46 => do_parse!(\n                        offset: be_u16 >>\n                        (TargetInfo::Offset {offset})\n                    ) |\n                    0x47 | 0x48 | 0x49 | 0x4A | 0x4B => do_parse!(\n                        offset: be_u16 >>\n                        type_argument_index: be_u8 >>\n                        (TargetInfo::TypeArgument {offset, type_argument_index})\n                    )\n                )\n            >> (inner)\n    )\n);\n\nnamed!(\n    type_path<attributes::TypePath>,\n    do_parse!(\n        type_path_kind: be_u8\n            >> type_argument_index: be_u8\n            >> (attributes::TypePath {\n                type_path_kind,\n                type_argument_index,\n            })\n    )\n);\n\nnamed_args!(type_annotation(cp: ConstantPool)<TypeAnnotation>, do_parse!(\n    target_info: target_info >>\n    target_path_part_count: be_u8 >>\n    target_path: count!(type_path, target_path_part_count as usize) >>\n    type_index: be_u16 >>\n    pair_count: be_u16 >>\n    pairs: count!(call!(element_value_pair, cp.clone()), pair_count as usize) >>\n    (attributes::TypeAnnotation {\n        target_info,\n        target_path,\n        type_index,\n        pairs,\n    })\n));\n\nnamed!(\n    bootstrap_method<attributes::BootstrapMethod>,\n    do_parse!(\n        method_ref: be_u16\n            >> arg_count: be_u16\n            >> args: count!(be_u16, arg_count as usize)\n            >> (attributes::BootstrapMethod { method_ref, args })\n    )\n);\n\nnamed!(\n    method_parameter<attributes::MethodParameter>,\n    do_parse!(\n        name_index: be_u16\n            >> acc_flags: be_u16\n            >> (attributes::MethodParameter {\n                name_index,\n                acc_flags\n            })\n    )\n);\n\nnamed!(\n    code_exception<attributes::CodeException>,\n    do_parse!(\n        start_pc: be_u16\n            >> end_pc: be_u16\n            >> handler_pc: be_u16\n            >> catch_type: be_u16\n            >> (attributes::CodeException {\n                start_pc,\n                end_pc,\n                handler_pc,\n                catch_type\n            })\n    )\n);\n\nnamed_args!(attr_sized(tag: AttrTag, self_len: usize, cp: ConstantPool)<AttributeType>, switch!(value!(tag),\n    AttrTag::ConstantValue => do_parse!(\n        constant_value_index: be_u16 >>\n        (AttributeType::ConstantValue {constant_value_index})\n    ) |\n    AttrTag::Code => do_parse!(\n        max_stack: be_u16 >>\n        max_locals: be_u16 >>\n        len: be_u32 >>\n        code: take!(len) >> // TODO: Parse code in same time?)\n        exception_count: be_u16 >>\n        exceptions: count!(code_exception, exception_count as usize) >>\n        attrs: call!(attr_type_vec, cp) >>\n        (AttributeType::Code(attributes::Code {\n            max_stack,\n            max_locals,\n            code: Arc::new(Vec::from(code)),\n            exceptions,\n            attrs,\n        }))\n    ) |\n    AttrTag::StackMapTable => do_parse!(\n        frame_count: be_u16 >>\n        frames: count!(stack_map_frame, frame_count as usize) >>\n        (AttributeType::StackMapTable { entries: frames })\n    ) |\n    AttrTag::Exceptions => do_parse!(\n        exception_count: be_u16 >>\n        exceptions: count!(be_u16, exception_count as usize) >>\n        (AttributeType::Exceptions { exceptions })\n    ) |\n    AttrTag::InnerClasses => do_parse!(\n        class_count: be_u16 >>\n        classes: count!(inner_class, class_count as usize) >>\n        (AttributeType::InnerClasses { classes })\n    ) |\n    AttrTag::EnclosingMethod => do_parse!(\n        em: enclosing_method >>\n        (AttributeType::EnclosingMethod { em })\n    ) |\n    AttrTag::Synthetic => value!(AttributeType::Synthetic) |\n    AttrTag::Signature => do_parse!(\n        signature_index: be_u16 >>\n        (AttributeType::Signature { signature_index })\n    ) |\n    AttrTag::SourceFile => do_parse!(\n        source_file_index: be_u16 >>\n        (AttributeType::SourceFile { source_file_index })\n    ) |\n    AttrTag::SourceDebugExtension => do_parse!(\n        debug_extension: take!(self_len) >>\n        (AttributeType::SourceDebugExtension { debug_extension: Arc::new(Vec::from(debug_extension)) })\n    ) |\n    AttrTag::LineNumberTable => do_parse!(\n        line_count: be_u16 >>\n        lines: count!(line_number, line_count as usize) >>\n        (AttributeType::LineNumberTable { tables: lines })\n    ) |\n    AttrTag::LocalVariableTable => do_parse!(\n        variable_count: be_u16 >>\n        variables: count!(local_variable, variable_count as usize) >>\n        (AttributeType::LocalVariableTable { tables: variables })\n    ) |\n    AttrTag::LocalVariableTypeTable => do_parse!(\n        variable_count: be_u16 >>\n        variables: count!(local_variable, variable_count as usize) >>\n        (AttributeType::LocalVariableTypeTable { tables: variables })\n    ) |\n    AttrTag::Deprecated => value!(AttributeType::Deprecated) |\n    AttrTag::RuntimeVisibleAnnotations => do_parse!(\n        raw: peek!(take!(self_len)) >>\n        annotation_count: be_u16 >>\n        annotations: count!(call!(annotation_entry, cp.clone()), annotation_count as usize) >>\n        (AttributeType::RuntimeVisibleAnnotations {raw: Arc::new(Vec::from(raw)), annotations})\n    ) |\n    AttrTag::RuntimeInvisibleAnnotations => do_parse!(\n        raw: peek!(take!(self_len)) >>\n        annotation_count: be_u16 >>\n        annotations: count!(call!(annotation_entry, cp.clone()), annotation_count as usize) >>\n        (AttributeType::RuntimeInvisibleAnnotations {raw: Arc::new(Vec::from(raw)), annotations})\n    ) |\n    AttrTag::RuntimeVisibleParameterAnnotations => do_parse!(\n        raw: peek!(take!(self_len)) >>\n        annotation_count: be_u16 >>\n        annotations: count!(call!(annotation_entry, cp.clone()), annotation_count as usize) >>\n        (AttributeType::RuntimeVisibleParameterAnnotations {raw: Arc::new(Vec::from(raw)), annotations})\n    ) |\n    AttrTag::RuntimeInvisibleParameterAnnotations => do_parse!(\n        raw: peek!(take!(self_len)) >>\n        annotation_count: be_u16 >>\n        annotations: count!(call!(annotation_entry, cp.clone()), annotation_count as usize) >>\n        (AttributeType::RuntimeInvisibleParameterAnnotations {raw: Arc::new(Vec::from(raw)), annotations})\n    ) |\n    AttrTag::RuntimeVisibleTypeAnnotations => do_parse!(\n        raw: peek!(take!(self_len)) >>\n        annotation_count: be_u16 >>\n        annotations: count!(call!(type_annotation, cp.clone()), annotation_count as usize) >>\n        (AttributeType::RuntimeVisibleTypeAnnotations {raw: Arc::new(Vec::from(raw)), annotations})\n    ) |\n    AttrTag::RuntimeInvisibleTypeAnnotations => do_parse!(\n        raw: peek!(take!(self_len)) >>\n        annotation_count: be_u16 >>\n        annotations: count!(call!(type_annotation, cp.clone()), annotation_count as usize) >>\n        (AttributeType::RuntimeInvisibleTypeAnnotations {raw: Arc::new(Vec::from(raw)), annotations})\n    ) |\n    AttrTag::AnnotationDefault => do_parse!(\n        raw: peek!(take!(self_len)) >>\n        default_value: call!(element_value_type, cp) >>\n        (AttributeType::AnnotationDefault {raw: Arc::new(Vec::from(raw)), default_value})\n    ) |\n    AttrTag::BootstrapMethods => do_parse!(\n        method_count: be_u16 >>\n        methods: count!(bootstrap_method, method_count as usize) >>\n        (AttributeType::BootstrapMethods {n:method_count, methods})\n    ) |\n    AttrTag::MethodParameters => do_parse!(\n        parameter_count: be_u8 >>\n        parameters: count!(method_parameter, parameter_count as usize) >>\n        (AttributeType::MethodParameters {parameters})\n    ) |\n    AttrTag::Unknown => do_parse!(\n        _data: take!(self_len) >>\n        (AttributeType::Unknown)\n    )\n));\n\nnamed_args!(attr_tag(cp: ConstantPool)<AttrTag>, do_parse!(\n    name_index: be_u16 >>\n    name: value!(constant_pool::get_utf8(&cp, name_index as usize)) >>\n    inner: value!(AttrTag::from(name.as_slice())) >>\n    (inner)\n));\n\nnamed_args!(attr_type(cp: ConstantPool)<AttributeType>, do_parse!(\n    tag: call!(attr_tag, cp.clone()) >>\n    length: be_u32 >>\n    attr: call!(attr_sized, tag, length as usize, cp) >>\n    (attr)\n));\n\nnamed_args!(attr_type_vec(cp: ConstantPool)<Vec<AttributeType>>, do_parse!(\n    attrs_count: be_u16 >>\n    attrs: count!(call!(attr_type, cp.clone()), attrs_count as usize) >>\n    (attrs)\n));\n\nnamed_args!(field(cp: ConstantPool)<FieldInfo>, do_parse!(\n    acc_flags: be_u16 >>\n    name_index: be_u16 >>\n    desc_index: be_u16 >>\n    attrs: call!(attr_type_vec, cp) >>\n    (FieldInfo {\n        acc_flags,\n        name_index,\n        desc_index,\n        attrs,\n    })\n));\n\nnamed_args!(method_info(cp: ConstantPool)<MethodInfo>, do_parse!(\n    acc_flags: be_u16 >>\n    name_index: be_u16 >>\n    desc_index: be_u16 >>\n    attrs: call!(attr_type_vec, cp) >>\n    (MethodInfo {\n        acc_flags,\n        name_index,\n        desc_index,\n        attrs,\n    })\n));\n\nnamed!(\n    class_file<ClassFile>,\n    do_parse!(\n        _magic: tag!(b\"\\xCA\\xFE\\xBA\\xBE\")\n            >> version: version\n            >> cp: constant_pool\n            >> acc_flags: be_u16\n            >> this_class: be_u16\n            >> super_class: be_u16\n            >> interfaces_count: be_u16\n            >> interfaces: count!(be_u16, interfaces_count as usize)\n            >> fields_count: be_u16\n            >> fields: count!(call!(field, cp.clone()), fields_count as usize)\n            >> method_count: be_u16\n            >> methods: count!(call!(method_info, cp.clone()), method_count as usize)\n            >> attrs: call!(attr_type_vec, cp.clone())\n            >> (ClassFile {\n                version,\n                cp: cp.clone(),\n                acc_flags,\n                this_class,\n                super_class,\n                interfaces,\n                fields,\n                methods,\n                attrs\n            })\n    )\n);\n\npub fn parse(input: &[u8]) -> nom::IResult<&[u8], ClassFile> {\n    class_file(input)\n}\n"
  },
  {
    "path": "crates/class-parser/src/lib.rs",
    "content": "#![allow(unused)]\n\nmod class;\nmod signature;\n\npub use class::parse as parse_class;\npub use signature::{ClassSignature, FieldSignature, MethodSignature};\n\n"
  },
  {
    "path": "crates/class-parser/src/signature.rs",
    "content": "use classfile::BytesRef;\nuse classfile::SignatureType as Type;\n\nuse nom::bytes::complete::{take, take_till};\nuse nom::character::complete::{char, one_of};\nuse nom::combinator::{peek, verify};\nuse nom::error::make_error;\nuse nom::lib::std::fmt::{Error, Formatter};\nuse nom::{\n    branch::alt,\n    bytes::complete::{is_not, tag},\n    error::{ErrorKind, ParseError, VerboseError},\n    multi::many1,\n    sequence::delimited,\n    AsBytes, Err, IResult,\n};\n\n#[derive(Debug)]\npub struct ClassSignature {\n    pub items: Vec<Type>,\n}\n\n#[derive(Debug, Clone)]\npub struct MethodSignature {\n    /*\n    TestNG, org.testng.collections.Maps\n\n    <K:Ljava/lang/Object;V:Ljava/lang/Object;>(Ljava/util/Map<TK;TV;>;)Ljava/util/Map<TK;TV;>;\n\n    public static <K extends java.lang.Object, V extends java.lang.Object> java.util.Map<K, V> newHashMap(java.util.Map<K, V>);\n    */\n    pub generics: Vec<(BytesRef, Type)>,\n\n    pub args: Vec<Type>,\n    pub retype: Type,\n}\n\npub struct FieldSignature {\n    pub field_type: Type,\n}\n\nimpl ClassSignature {\n    pub fn new(raw: &[u8]) -> Self {\n        let s = unsafe { std::str::from_utf8_unchecked(raw) };\n        let (_, cs) = Self::parse(s).unwrap();\n        cs\n    }\n\n    fn parse(i: &str) -> IResult<&str, ClassSignature> {\n        let (i, items) = parse_types(i)?;\n        Ok((i, ClassSignature { items }))\n    }\n}\n\nimpl MethodSignature {\n    pub fn new(raw: &[u8]) -> Self {\n        let s = unsafe { std::str::from_utf8_unchecked(raw) };\n        let (_, r) = Self::parse(s).unwrap();\n        r\n    }\n\n    fn parse(i: &str) -> IResult<&str, MethodSignature> {\n        fn arg0(i: &str) -> IResult<&str, MethodSignature> {\n            let (i, _) = tag(\"()\")(i)?;\n            let (i, retype) = parse_type(i)?;\n            Ok((\n                i,\n                MethodSignature {\n                    generics: vec![],\n                    args: vec![],\n                    retype,\n                },\n            ))\n        }\n\n        fn args(i: &str) -> IResult<&str, MethodSignature> {\n            let (i_return, i_args) = delimited(char('('), is_not(\")\"), char(')'))(i)?;\n            let (_, args) = parse_types(i_args)?;\n            let (i, retype) = parse_type(i_return)?;\n            Ok((\n                i,\n                MethodSignature {\n                    generics: vec![],\n                    args,\n                    retype,\n                },\n            ))\n        }\n\n        fn generic(i: &str) -> IResult<&str, MethodSignature> {\n            let (i, _) = tag(\"<\")(i)?;\n            let (i, generics) = many1(generic_declare)(i)?;\n            let (i, _) = tag(\">\")(i)?;\n            let (i, mut r) = MethodSignature::parse(i)?;\n\n            r.generics = generics;\n\n            Ok((i, r))\n        }\n\n        alt((arg0, args, generic))(i)\n    }\n}\n\nimpl FieldSignature {\n    pub fn new(raw: &[u8]) -> Self {\n        let s = unsafe { std::str::from_utf8_unchecked(raw) };\n        let (_, r) = Self::parse(s).unwrap();\n        r\n    }\n\n    fn parse(mut i: &str) -> IResult<&str, FieldSignature> {\n        let (i, field_type) = parse_type(i)?;\n        Ok((i, FieldSignature { field_type }))\n    }\n}\n\nimpl Default for MethodSignature {\n    fn default() -> Self {\n        Self {\n            generics: Vec::new(),\n            args: Vec::new(),\n            retype: Type::Void,\n        }\n    }\n}\n\n///////////////////////////\n//parser\n///////////////////////////\n\nfn primitive<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&str, Type, E> {\n    let (i, t) = one_of(\"BCDFIJSZV\")(i)?;\n    let t = match t {\n        'B' => Type::Byte,\n        'C' => Type::Char,\n        'D' => Type::Double,\n        'F' => Type::Float,\n        'I' => Type::Int,\n        'J' => Type::Long,\n        'S' => Type::Short,\n        'Z' => Type::Boolean,\n        'V' => Type::Void,\n        _ => unreachable!(),\n    };\n\n    Ok((i, t))\n}\n\nfn object_desc<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&str, BytesRef, E> {\n    // should stop when reach ';' or '<'\n    //such as:\n    //(Lorg/testng/internal/IConfiguration;Lorg/testng/ISuite;Lorg/testng/xml/XmlTest;Ljava/lang/String;Lorg/testng/internal/annotations/IAnnotationFinder;ZLjava/util/List<Lorg/testng/IInvokedMethodListener;>;)V\n    // if only take_till(|c| c == ';'), can't process like:\n    //    Lxx/xx/xx<Lxx/xx/xx;>;\n    let (_, _) = alt((tag(\"L\"), tag(\"T\")))(input)?;\n    let (i, desc) = take_till(|c| c == ';' || c == '<')(input)?;\n    let (i, _) = tag(\";\")(i)?;\n    let mut buf = Vec::with_capacity(1 + desc.len() + 1);\n    buf.extend_from_slice(desc.as_bytes());\n    buf.push(b';');\n    let desc = std::sync::Arc::new(buf);\n    Ok((i, desc))\n}\n\nfn object_generic<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&str, Type, E> {\n    let (i, tag_prefix) = alt((tag(\"L\"), tag(\"T\")))(i)?;\n    let (i, container) = take_till(|c| c == '<')(i)?;\n    let (mut i, _) = tag(\"<\")(i)?;\n\n    //signature like:\n    //Ljava/lang/Class<+Lcom/google/inject/Module;>;\n    //<=> 'java.lang.Class<? extends com.google.inject.Module>'\n    let mut prefix = None;\n    if i.starts_with('+') {\n        prefix = Some(b'+');\n        let (i2, _) = tag(\"+\")(i)?;\n        i = i2;\n    }\n\n    let (i, generic_args) = many1(parse_type)(i)?;\n    let (i, _) = tag(\">\")(i)?;\n    let (i, _) = tag(\";\")(i)?;\n\n    //build results\n    let mut buf = Vec::with_capacity(1 + container.len() + 1);\n    buf.extend_from_slice(tag_prefix.as_bytes());\n    buf.extend_from_slice(container.as_bytes());\n    buf.push(b';');\n    let desc = std::sync::Arc::new(buf);\n    Ok((i, Type::Object(desc, Some(generic_args), prefix)))\n}\n\nfn object_normal<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&str, Type, E> {\n    let (i, _) = peek(alt((tag(\"L\"), tag(\"T\"))))(i)?;\n    let (i, desc) = object_desc(i)?;\n    Ok((i, Type::Object(desc, None, None)))\n}\n\nfn object<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&str, Type, E> {\n    alt((object_normal, object_generic))(i)\n}\n\nfn array<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&str, Type, E> {\n    let (i, _) = peek(tag(\"[\"))(i)?;\n    let (i, ary_tags) = take_till(|c| c != '[')(i)?;\n    let (mut i, t) = peek(take(1u8))(i)?;\n\n    let mut buf = vec![];\n    buf.extend_from_slice(ary_tags.as_bytes());\n    match t {\n        \"L\" | \"T\" => {\n            let (i2, desc) = object_desc(i)?;\n            i = i2;\n            buf.extend_from_slice(desc.as_slice());\n        }\n        v => {\n            let (i2, _) = take(1u8)(i)?;\n            i = i2;\n            buf.extend_from_slice(v.as_bytes())\n        }\n    }\n    let desc = std::sync::Arc::new(buf);\n    Ok((i, Type::Array(desc)))\n}\n\nfn generic_declare<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&str, (BytesRef, Type), E> {\n    let (i, generic_type) = take_till(|c| c == ':')(i)?;\n    let (i, _) = tag(\":\")(i)?;\n    let (i, t) = parse_type(i)?;\n    let generic_type = std::sync::Arc::new(Vec::from(generic_type));\n    Ok((i, (generic_type, t)))\n}\n\nfn parse_type<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&str, Type, E> {\n    alt((primitive, object, array))(i)\n}\n\nfn parse_types<'a, E: ParseError<&'a str>>(mut input: &'a str) -> IResult<&str, Vec<Type>, E> {\n    let it = std::iter::from_fn(move || {\n        match parse_type::<'a, E>(input) {\n            // when successful, a nom parser returns a tuple of\n            // the remaining input and the output value.\n            // So we replace the captured input data with the\n            // remaining input, to be parsed on the next call\n            Ok((i, o)) => {\n                input = i;\n                Some(o)\n            }\n            _ => None,\n        }\n    });\n\n    let mut args = vec![];\n    for v in it {\n        args.push(v);\n    }\n\n    Ok((input, args))\n}\n\n#[cfg(test)]\nmod tests {\n    use super::ClassSignature;\n    use super::FieldSignature;\n    use super::MethodSignature;\n    use super::Type as SignatureType;\n    use std::sync::Arc;\n\n    #[test]\n    fn t_method_no_arg() {\n        let expected = MethodSignature {\n            generics: vec![],\n            args: vec![],\n            retype: SignatureType::Void,\n        };\n        let (_, r) = MethodSignature::parse(\"()V\").unwrap();\n        assert_eq!(r.args, expected.args);\n        assert_eq!(r.retype, expected.retype);\n    }\n\n    #[test]\n    fn method_primitive() {\n        let table = vec![\n            (\n                MethodSignature {\n                    generics: vec![],\n                    args: vec![SignatureType::Byte],\n                    retype: SignatureType::Void,\n                },\n                \"(B)V\",\n            ),\n            (\n                MethodSignature {\n                    generics: vec![],\n                    args: vec![SignatureType::Char],\n                    retype: SignatureType::Void,\n                },\n                \"(C)V\",\n            ),\n            (\n                MethodSignature {\n                    generics: vec![],\n                    args: vec![SignatureType::Double],\n                    retype: SignatureType::Void,\n                },\n                \"(D)V\",\n            ),\n            (\n                MethodSignature {\n                    generics: vec![],\n                    args: vec![SignatureType::Float],\n                    retype: SignatureType::Void,\n                },\n                \"(F)V\",\n            ),\n            (\n                MethodSignature {\n                    generics: vec![],\n                    args: vec![SignatureType::Int],\n                    retype: SignatureType::Void,\n                },\n                \"(I)V\",\n            ),\n            (\n                MethodSignature {\n                    generics: vec![],\n                    args: vec![SignatureType::Long],\n                    retype: SignatureType::Void,\n                },\n                \"(J)V\",\n            ),\n            (\n                MethodSignature {\n                    generics: vec![],\n                    args: vec![SignatureType::Short],\n                    retype: SignatureType::Void,\n                },\n                \"(S)V\",\n            ),\n            (\n                MethodSignature {\n                    generics: vec![],\n                    args: vec![SignatureType::Boolean],\n                    retype: SignatureType::Void,\n                },\n                \"(Z)V\",\n            ),\n        ];\n\n        for (expected, desc) in table.iter() {\n            let (_, r) = MethodSignature::parse(desc).unwrap();\n            assert_eq!(r.args, expected.args);\n            assert_eq!(r.retype, expected.retype);\n        }\n    }\n\n    #[test]\n    fn method_array_object() {\n        let expected = MethodSignature {\n            generics: vec![],\n            args: vec![SignatureType::Array(Arc::new(Vec::from(\n                \"[[Ljava/lang/String;\",\n            )))],\n            retype: SignatureType::Void,\n        };\n        let (_, r) = MethodSignature::parse(\"([[Ljava/lang/String;)V\").unwrap();\n        assert_eq!(r.args, expected.args);\n        assert_eq!(r.retype, expected.retype);\n    }\n\n    #[test]\n    fn method_mix() {\n        let expected = MethodSignature {\n            generics: vec![],\n            args: vec![\n                SignatureType::Byte,\n                SignatureType::Char,\n                SignatureType::Double,\n                SignatureType::Float,\n                SignatureType::Int,\n                SignatureType::Long,\n                SignatureType::Short,\n                SignatureType::Boolean,\n                SignatureType::Object(Arc::new(Vec::from(\"Ljava/lang/Integer;\")), None, None),\n            ],\n            retype: SignatureType::Object(Arc::new(Vec::from(\"Ljava/lang/String;\")), None, None),\n        };\n        let (_, r) =\n            MethodSignature::parse(\"(BCDFIJSZLjava/lang/Integer;)Ljava/lang/String;\").unwrap();\n        assert_eq!(r.args, expected.args);\n        assert_eq!(r.retype, expected.retype);\n    }\n\n    #[test]\n    fn method_arg_generic() {\n        let generic_args = vec![SignatureType::Object(\n            Arc::new(Vec::from(\"Ljava/lang/String;\")),\n            None,\n            None,\n        )];\n        let expected = MethodSignature {\n            generics: vec![],\n            args: vec![SignatureType::Object(\n                Arc::new(Vec::from(\"Ljava/util/List;\")),\n                Some(generic_args),\n                None,\n            )],\n            retype: SignatureType::Void,\n        };\n        let (_, r) = MethodSignature::parse(\"(Ljava/util/List<Ljava/lang/String;>;)V\").unwrap();\n        assert_eq!(r.args, expected.args);\n        assert_eq!(r.retype, expected.retype);\n\n        let expected = MethodSignature {\n            generics: vec![],\n            args: vec![\n                SignatureType::Object(\n                    Arc::new(Vec::from(\"Lorg/testng/internal/IConfiguration;\")),\n                    None,\n                    None,\n                ),\n                SignatureType::Object(Arc::new(Vec::from(\"Lorg/testng/ISuite;\")), None, None),\n                SignatureType::Object(Arc::new(Vec::from(\"Lorg/testng/xml/XmlTest;\")), None, None),\n                SignatureType::Object(Arc::new(Vec::from(\"Ljava/lang/String;\")), None, None),\n                SignatureType::Object(\n                    Arc::new(Vec::from(\n                        \"Lorg/testng/internal/annotations/IAnnotationFinder;\",\n                    )),\n                    None,\n                    None,\n                ),\n                SignatureType::Boolean,\n                SignatureType::Object(\n                    Arc::new(Vec::from(\"Ljava/util/List;\")),\n                    Some(vec![SignatureType::Object(\n                        Arc::new(Vec::from(\"Lorg/testng/IInvokedMethodListener;\")),\n                        None,\n                        None,\n                    )]),\n                    None,\n                ),\n            ],\n            retype: SignatureType::Void,\n        };\n        let (_, r) = MethodSignature::parse(\"(Lorg/testng/internal/IConfiguration;Lorg/testng/ISuite;Lorg/testng/xml/XmlTest;Ljava/lang/String;Lorg/testng/internal/annotations/IAnnotationFinder;ZLjava/util/List<Lorg/testng/IInvokedMethodListener;>;)V\").unwrap();\n        assert_eq!(r.args, expected.args);\n        assert_eq!(r.retype, expected.retype);\n    }\n\n    #[test]\n    fn generic1() {\n        let expected = MethodSignature {\n            generics: vec![],\n            args: vec![\n                SignatureType::Object(Arc::new(Vec::from(\"TK;\")), None, None),\n                SignatureType::Object(Arc::new(Vec::from(\"TV;\")), None, None),\n            ],\n            retype: SignatureType::Void,\n        };\n        let (_, r) = MethodSignature::parse(\"(TK;TV;)V\").unwrap();\n        assert_eq!(r.args, expected.args);\n        assert_eq!(r.retype, expected.retype);\n    }\n\n    //'T' tag in args\n    #[test]\n    fn generic2() {\n        let expected = MethodSignature {\n            generics: vec![],\n            args: vec![SignatureType::Object(\n                Arc::new(Vec::from(\"TK;\")),\n                None,\n                None,\n            )],\n            retype: SignatureType::Object(\n                Arc::new(Vec::from(\"Ljava/util/Set;\")),\n                Some(vec![SignatureType::Object(\n                    Arc::new(Vec::from(\"TV;\")),\n                    None,\n                    None,\n                )]),\n                None,\n            ),\n        };\n        let (_, r) = MethodSignature::parse(\"(TK;)Ljava/util/Set<TV;>;\").unwrap();\n        assert_eq!(r.args, expected.args);\n        assert_eq!(r.retype, expected.retype);\n    }\n\n    #[test]\n    fn generic_nest1() {\n        let expected = MethodSignature {\n            generics: vec![],\n            args: vec![],\n            retype: SignatureType::Object(\n                Arc::new(Vec::from(\"Ljava/util/Set;\")),\n                Some(vec![SignatureType::Object(\n                    Arc::new(Vec::from(\"Ljava/util/Map$Entry;\")),\n                    Some(vec![\n                        SignatureType::Object(Arc::new(Vec::from(\"TK;\")), None, None),\n                        SignatureType::Object(\n                            Arc::new(Vec::from(\"Ljava/util/Set;\")),\n                            Some(vec![SignatureType::Object(\n                                Arc::new(Vec::from(\"TV;\")),\n                                None,\n                                None,\n                            )]),\n                            None,\n                        ),\n                    ]),\n                    None,\n                )]),\n                None,\n            ),\n        };\n        let (_, r) = MethodSignature::parse(\n            \"()Ljava/util/Set<Ljava/util/Map$Entry<TK;Ljava/util/Set<TV;>;>;>;\",\n        )\n        .unwrap();\n        assert_eq!(r.args, expected.args);\n        assert_eq!(r.retype, expected.retype);\n    }\n\n    #[test]\n    fn generic_method() {\n        let expected = MethodSignature {\n            generics: vec![\n                (\n                    Arc::new(Vec::from(\"K\")),\n                    SignatureType::Object(Arc::new(Vec::from(\"Ljava/lang/Object;\")), None, None),\n                ),\n                (\n                    Arc::new(Vec::from(\"V\")),\n                    SignatureType::Object(Arc::new(Vec::from(\"Ljava/lang/Object;\")), None, None),\n                ),\n            ],\n            args: vec![SignatureType::Object(\n                Arc::new(Vec::from(\"Ljava/util/Map;\")),\n                Some(vec![\n                    SignatureType::Object(Arc::new(Vec::from(\"TK;\")), None, None),\n                    SignatureType::Object(Arc::new(Vec::from(\"TV;\")), None, None),\n                ]),\n                None,\n            )],\n            retype: SignatureType::Object(\n                Arc::new(Vec::from(\"Ljava/util/Map;\")),\n                Some(vec![\n                    SignatureType::Object(Arc::new(Vec::from(\"TK;\")), None, None),\n                    SignatureType::Object(Arc::new(Vec::from(\"TV;\")), None, None),\n                ]),\n                None,\n            ),\n        };\n        let (_, r) = MethodSignature::parse(\"<K:Ljava/lang/Object;V:Ljava/lang/Object;>(Ljava/util/Map<TK;TV;>;)Ljava/util/Map<TK;TV;>;\").unwrap();\n        assert_eq!(r.args, expected.args);\n        assert_eq!(r.retype, expected.retype);\n    }\n\n    #[test]\n    fn method_return_generic() {\n        let generic_args = vec![SignatureType::Object(\n            Arc::new(Vec::from(\"Lorg/testng/ITestNGListener;\")),\n            None,\n            None,\n        )];\n        let expected = MethodSignature {\n            generics: vec![],\n            args: vec![],\n            retype: SignatureType::Object(\n                Arc::new(Vec::from(\"Ljava/util/List;\")),\n                Some(generic_args),\n                None,\n            ),\n        };\n        let (_, r) =\n            MethodSignature::parse(\"()Ljava/util/List<Lorg/testng/ITestNGListener;>;\").unwrap();\n        assert_eq!(r.args, expected.args);\n        assert_eq!(r.retype, expected.retype);\n    }\n\n    #[test]\n    fn field() {\n        macro_rules! setup_test {\n            ($desc: expr, $tp: expr) => {\n                let (_, sig) = FieldSignature::parse($desc).unwrap();\n                assert_eq!(sig.field_type, $tp);\n            };\n        }\n\n        setup_test!(\"B\", SignatureType::Byte);\n        setup_test!(\"C\", SignatureType::Char);\n        setup_test!(\"D\", SignatureType::Double);\n        setup_test!(\"F\", SignatureType::Float);\n        setup_test!(\"I\", SignatureType::Int);\n        setup_test!(\"J\", SignatureType::Long);\n\n        let v = Vec::from(\"Ljava/lang/Object;\");\n        let v = Arc::new(v);\n        setup_test!(\"Ljava/lang/Object;\", SignatureType::Object(v, None, None));\n        setup_test!(\"S\", SignatureType::Short);\n        setup_test!(\"Z\", SignatureType::Boolean);\n\n        let v = Vec::from(\"[Ljava/lang/Object;\");\n        let v = Arc::new(v);\n        setup_test!(\"[Ljava/lang/Object;\", SignatureType::Array(v));\n\n        let v = Vec::from(\"[[[D\");\n        let v = Arc::new(v);\n        setup_test!(\"[[[D\", SignatureType::Array(v));\n    }\n\n    #[test]\n    fn t_class_signature() {\n        let (_, cs) = ClassSignature::parse(\"Ljava/lang/Object;Lorg/testng/ITestContext;Lorg/testng/internal/ITestResultNotifier;Lorg/testng/internal/thread/graph/IThreadWorkerFactory<Lorg/testng/ITestNGMethod;>;\").unwrap();\n        let expected = ClassSignature {\n            items: vec![\n                SignatureType::Object(Arc::new(Vec::from(\"Ljava/lang/Object;\")), None, None),\n                SignatureType::Object(Arc::new(Vec::from(\"Lorg/testng/ITestContext;\")), None, None),\n                SignatureType::Object(\n                    Arc::new(Vec::from(\"Lorg/testng/internal/ITestResultNotifier;\")),\n                    None,\n                    None,\n                ),\n                SignatureType::Object(\n                    Arc::new(Vec::from(\n                        \"Lorg/testng/internal/thread/graph/IThreadWorkerFactory;\",\n                    )),\n                    Some(vec![SignatureType::Object(\n                        Arc::new(Vec::from(\"Lorg/testng/ITestNGMethod;\")),\n                        None,\n                        None,\n                    )]),\n                    None,\n                ),\n            ],\n        };\n        assert_eq!(cs.items, expected.items);\n    }\n}\n"
  },
  {
    "path": "crates/class-verification/Cargo.toml",
    "content": "[package]\nname = \"class-verification\"\nversion = \"0.1.0\"\nauthors = [\"Dou Chuan <1843657913@qq.com>\"]\nedition = \"2018\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\n"
  },
  {
    "path": "crates/class-verification/src/checker.rs",
    "content": "use crate::types::ConstantPool;\n\n#[derive(Debug, Clone, Copy, PartialEq)]\npub enum Err {\n    InvalidCpClassNameIdx,\n    InvalidCpFieldRefClsIdx,\n    InvalidCpFieldRefNameAndTypeIdx,\n    InvalidCpMethodRefClsIdx,\n    InvalidCpMethodRefNameAndTypeIdx,\n    InvalidCpInterfaceMethodRefClsIdx,\n    InvalidCpInterfaceMethodRefNameAndTypeIdx,\n    InvalidCpStrStrIdx,\n    InvalidCpNameAndTypeNameIdx,\n    InvalidCpNameAndTypeDescIdx,\n    InvalidCpMethodHandleRefKind,\n    InvalidCpMethodHandleRefIdx,\n    InvalidCpMethodTypeDescIdx,\n    InvalidCpInvokeDynBootstrapMethodAttrIdx,\n    InvalidCpInvokeDynNameAndTypeIdx,\n    InvalidFieldAccFlags,\n    InvalidFieldNameIdx,\n    InvalidFieldDescIdx,\n    InvalidMethodAccFlags,\n    InvalidMethodNameIdx,\n    InvalidMethodDescIdx,\n}\n\npub type CheckResult = Result<(), Err>;\n\npub trait Checker {\n    fn check(&self, cp: &ConstantPool) -> CheckResult;\n}\n"
  },
  {
    "path": "crates/class-verification/src/lib.rs",
    "content": ""
  },
  {
    "path": "crates/classfile/Cargo.toml",
    "content": "[package]\nname = \"classfile\"\nversion = \"0.1.0\"\nauthors = [\"Dou Chuan <1843657913@qq.com>\"]\nedition = \"2018\"\nlicense = \"MIT OR Apache-2.0\"\ndescription = \"Types for the class file format of the Java Virtual Machine.\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\nlog = \"0.4.0\"\nlazy_static = \"1.4.0\"\n"
  },
  {
    "path": "crates/classfile/README.md",
    "content": "## JVM class file\nThis is the `classfile` crate, which contains definition of\nclass file format of Java Virtual Machine.\nThe spec based on `Java SE 8 Edition`."
  },
  {
    "path": "crates/classfile/src/attributes.rs",
    "content": "use crate::{BytesRef, U1, U2, U4};\nuse std::sync::Arc;\n\n#[derive(Debug, Clone)]\npub enum Type {\n    ConstantValue {\n        constant_value_index: U2,\n    },\n    Code(Code),\n    StackMapTable {\n        entries: Vec<StackMapFrame>,\n    },\n    Exceptions {\n        exceptions: Vec<U2>,\n    },\n    InnerClasses {\n        classes: Vec<InnerClass>,\n    },\n    EnclosingMethod {\n        em: EnclosingMethod,\n    },\n    Synthetic,\n    Signature {\n        signature_index: U2,\n    },\n    SourceFile {\n        source_file_index: U2,\n    },\n    SourceDebugExtension {\n        debug_extension: BytesRef,\n    },\n    LineNumberTable {\n        tables: Vec<LineNumber>,\n    },\n    LocalVariableTable {\n        tables: Vec<LocalVariable>,\n    },\n    LocalVariableTypeTable {\n        tables: Vec<LocalVariable>,\n    },\n    Deprecated,\n    RuntimeVisibleAnnotations {\n        raw: BytesRef,\n        annotations: Vec<AnnotationEntry>,\n    },\n    RuntimeInvisibleAnnotations {\n        raw: BytesRef,\n        annotations: Vec<AnnotationEntry>,\n    },\n    RuntimeVisibleParameterAnnotations {\n        raw: BytesRef,\n        annotations: Vec<AnnotationEntry>,\n    },\n    RuntimeInvisibleParameterAnnotations {\n        raw: BytesRef,\n        annotations: Vec<AnnotationEntry>,\n    },\n    RuntimeVisibleTypeAnnotations {\n        raw: BytesRef,\n        annotations: Vec<TypeAnnotation>,\n    },\n    RuntimeInvisibleTypeAnnotations {\n        raw: BytesRef,\n        annotations: Vec<TypeAnnotation>,\n    },\n    AnnotationDefault {\n        raw: BytesRef,\n        default_value: ElementValueType,\n    },\n    BootstrapMethods {\n        n: U2,\n        methods: Vec<BootstrapMethod>,\n    },\n    MethodParameters {\n        parameters: Vec<MethodParameter>,\n    },\n    Unknown,\n}\n\n#[derive(Clone, Copy)]\npub enum Tag {\n    ConstantValue,\n    Code,\n    StackMapTable,\n    Exceptions,\n    InnerClasses,\n    EnclosingMethod,\n    Synthetic,\n    Signature,\n    SourceFile,\n    SourceDebugExtension,\n    LineNumberTable,\n    LocalVariableTable,\n    LocalVariableTypeTable,\n    Deprecated,\n    RuntimeVisibleAnnotations,\n    RuntimeInvisibleAnnotations,\n    RuntimeVisibleParameterAnnotations,\n    RuntimeInvisibleParameterAnnotations,\n    RuntimeVisibleTypeAnnotations,\n    RuntimeInvisibleTypeAnnotations,\n    AnnotationDefault,\n    BootstrapMethods,\n    MethodParameters,\n    Unknown,\n}\n\nimpl From<&[u8]> for Tag {\n    fn from(raw: &[u8]) -> Self {\n        match raw {\n            b\"ConstantValue\" => Tag::ConstantValue,\n            b\"Code\" => Tag::Code,\n            b\"StackMapTable\" => Tag::StackMapTable,\n            b\"Exceptions\" => Tag::Exceptions,\n            b\"InnerClasses\" => Tag::InnerClasses,\n            b\"EnclosingMethod\" => Tag::EnclosingMethod,\n            b\"Synthetic\" => Tag::Synthetic,\n            b\"Signature\" => Tag::Signature,\n            b\"SourceFile\" => Tag::SourceFile,\n            b\"SourceDebugExtension\" => Tag::SourceDebugExtension,\n            b\"LineNumberTable\" => Tag::LineNumberTable,\n            b\"LocalVariableTable\" => Tag::LocalVariableTable,\n            b\"LocalVariableTypeTable\" => Tag::LocalVariableTypeTable,\n            b\"Deprecated\" => Tag::Deprecated,\n            b\"RuntimeVisibleAnnotations\" => Tag::RuntimeVisibleAnnotations,\n            b\"RuntimeInvisibleAnnotations\" => Tag::RuntimeInvisibleAnnotations,\n            b\"RuntimeVisibleParameterAnnotations\" => Tag::RuntimeVisibleParameterAnnotations,\n            b\"RuntimeInvisibleParameterAnnotations\" => Tag::RuntimeInvisibleParameterAnnotations,\n            b\"RuntimeVisibleTypeAnnotations\" => Tag::RuntimeVisibleTypeAnnotations,\n            b\"RuntimeInvisibleTypeAnnotations\" => Tag::RuntimeInvisibleTypeAnnotations,\n            b\"AnnotationDefault\" => Tag::AnnotationDefault,\n            b\"BootstrapMethods\" => Tag::BootstrapMethods,\n            b\"MethodParameters\" => Tag::MethodParameters,\n            _ => {\n                info!(\"Unknown attr {}\", unsafe {\n                    std::str::from_utf8_unchecked(raw)\n                });\n                // error!(\"Unknown attr {}\", String::from_utf8_lossy(raw));\n                Tag::Unknown\n            }\n        }\n    }\n}\n\n#[derive(Debug, Clone)]\npub struct Code {\n    pub max_stack: U2,\n    pub max_locals: U2,\n    pub code: Arc<Vec<U1>>,\n    pub exceptions: Vec<CodeException>,\n    pub attrs: Vec<Type>,\n}\n\n#[derive(Debug, Clone)]\npub struct CodeException {\n    pub start_pc: U2,\n    pub end_pc: U2,\n    pub handler_pc: U2,\n    pub catch_type: U2,\n}\n\nimpl CodeException {\n    pub fn contains(&self, pc: U2) -> bool {\n        (self.start_pc..self.end_pc + 1).contains(&pc)\n    }\n\n    pub fn is_finally(&self) -> bool {\n        self.catch_type == 0\n    }\n}\n\n#[derive(Debug, Clone)]\npub struct AttributeInfo {\n    pub name_index: U2,\n    pub length: U4,\n    pub info: Vec<U1>,\n}\n\npub enum NestedClassAccessPropertyFlag {\n    AccPublic,\n    AccPrivate,\n    AccProtected,\n    AccStatic,\n    AccFinal,\n    AccInterface,\n    AccAbstract,\n    AccSynthetic,\n    AccAnnotation,\n    AccEnum,\n}\n\n#[derive(Debug, Copy, Clone)]\npub struct InnerClass {\n    pub inner_class_info_index: U2,\n    pub outer_class_info_index: U2,\n    pub inner_name_index: U2,\n    pub inner_class_access_flags: U2,\n}\n\n#[derive(Debug, Copy, Clone)]\npub struct LineNumber {\n    pub start_pc: U2,\n    pub number: U2,\n}\n\n#[derive(Debug, Copy, Clone)]\npub struct LocalVariable {\n    pub start_pc: U2,\n    pub length: U2,\n    pub name_index: U2,\n    pub signature_index: U2,\n    pub index: U2,\n}\n\n#[derive(Debug, Clone, Copy)]\npub enum ElementValueTag {\n    Byte,\n    Char,\n    Double,\n    Float,\n    Int,\n    Long,\n    Short,\n    Boolean,\n    String,\n    Enum,\n    Class,\n    Annotation,\n    Array,\n    Unknown,\n}\n\nimpl From<u8> for ElementValueTag {\n    fn from(v: u8) -> Self {\n        match v {\n            b'B' => ElementValueTag::Byte,\n            b'C' => ElementValueTag::Char,\n            b'D' => ElementValueTag::Double,\n            b'F' => ElementValueTag::Float,\n            b'I' => ElementValueTag::Int,\n            b'J' => ElementValueTag::Long,\n            b'S' => ElementValueTag::Short,\n            b'Z' => ElementValueTag::Boolean,\n            b's' => ElementValueTag::String,\n            b'e' => ElementValueTag::Enum,\n            b'c' => ElementValueTag::Class,\n            b'@' => ElementValueTag::Annotation,\n            b'[' => ElementValueTag::Array,\n            _ => ElementValueTag::Unknown,\n        }\n    }\n}\n\n#[derive(Debug, Clone)]\npub enum ElementValueType {\n    Byte { val_index: U2 },\n    Char { val_index: U2 },\n    Double { val_index: U2 },\n    Float { val_index: U2 },\n    Int { val_index: U2 },\n    Long { val_index: U2 },\n    Short { val_index: U2 },\n    Boolean { val_index: U2 },\n    String { val_index: U2 },\n    Enum { type_index: U2, val_index: U2 },\n    Class { index: U2 },\n    Annotation(AnnotationElementValue),\n    Array { values: Vec<ElementValueType> },\n    Unknown,\n}\n\n#[derive(Debug, Clone)]\npub struct AnnotationElementValue {\n    pub value: AnnotationEntry,\n}\n\n#[derive(Debug, Clone)]\npub struct ElementValuePair {\n    pub name_index: U2,\n    pub value: ElementValueType,\n}\n\n#[derive(Debug, Clone)]\npub struct AnnotationEntry {\n    pub type_name: BytesRef,\n    pub pairs: Vec<ElementValuePair>,\n}\n\n#[derive(Debug, Clone)]\npub struct BootstrapMethod {\n    pub method_ref: U2,\n    pub args: Vec<U2>,\n}\n\n#[derive(Debug)]\npub enum MethodParameterAccessFlag {\n    AccFinal = 0x0010,\n    AccSynthetic = 0x1000,\n    AccMandated = 0x8000,\n}\n\n#[derive(Debug, Copy, Clone)]\npub struct MethodParameter {\n    pub name_index: U2,\n    pub acc_flags: U2,\n}\n\n#[derive(Debug, Clone)]\npub enum VerificationTypeInfo {\n    Top,\n    Integer,\n    Float,\n    Long,\n    Double,\n    Null,\n    UninitializedThis,\n    Object { cpool_index: U2 },\n    Uninitialized { offset: U2 },\n}\n\n#[derive(Debug, Clone)]\npub enum StackMapFrame {\n    Same {\n        tag: U1,\n        offset_delta: U2,\n    },\n    SameLocals1StackItem {\n        tag: U1,\n        offset_delta: U2,\n        stack: [VerificationTypeInfo; 1],\n    },\n    SameLocals1StackItemExtended {\n        tag: U1,\n        offset_delta: U2,\n        stack: [VerificationTypeInfo; 1],\n    },\n    Chop {\n        tag: U1,\n        offset_delta: U2,\n    },\n    SameExtended {\n        tag: U1,\n        offset_delta: U2,\n    },\n    Append {\n        tag: U1,\n        offset_delta: U2,\n        locals: Vec<VerificationTypeInfo>,\n    },\n    Full {\n        tag: U1,\n        offset_delta: U2,\n        locals: Vec<VerificationTypeInfo>,\n        stack: Vec<VerificationTypeInfo>,\n    },\n    Reserved(U1),\n}\n\n#[derive(Debug, Clone)]\npub struct TypeAnnotation {\n    pub target_info: TargetInfo,\n    pub target_path: Vec<TypePath>,\n    pub type_index: U2,\n    pub pairs: Vec<ElementValuePair>,\n}\n\n#[derive(Debug, Clone)]\npub enum TargetInfo {\n    TypeParameter {\n        type_parameter_index: U1,\n    },\n    SuperType {\n        supertype_index: U2,\n    },\n    TypeParameterBound {\n        type_parameter_index: U1,\n        bound_index: U1,\n    },\n    Empty,\n    FormalParameter {\n        formal_parameter_index: U1,\n    },\n    Throws {\n        throws_type_index: U2,\n    },\n    LocalVar {\n        table: Vec<LocalVarTargetTable>,\n    },\n    Catch {\n        exception_table_index: U2,\n    },\n    Offset {\n        offset: U2,\n    },\n    TypeArgument {\n        offset: U2,\n        type_argument_index: U1,\n    },\n}\n\n#[derive(Debug, Clone)]\npub struct LocalVarTargetTable {\n    pub start_pc: U2,\n    pub length: U2,\n    pub index: U2,\n}\n\n#[derive(Debug, Clone)]\npub struct TypePath {\n    pub type_path_kind: U1,\n    pub type_argument_index: U1,\n}\n\n#[derive(Debug, Clone)]\npub struct EnclosingMethod {\n    pub class_index: U2,\n    pub method_index: U2,\n}\n"
  },
  {
    "path": "crates/classfile/src/classfile.rs",
    "content": "use crate::attributes::InnerClass;\nuse crate::{attributes::Type, field_info::FieldInfo, method_info::MethodInfo, version::Version};\nuse crate::{ConstantPool, U2};\n\n#[derive(Debug)]\npub struct ClassFile {\n    pub version: Version,\n    pub cp: ConstantPool,\n    pub acc_flags: U2,\n    pub this_class: U2,\n    pub super_class: U2,\n    pub interfaces: Vec<U2>,\n    pub fields: Vec<FieldInfo>,\n    pub methods: Vec<MethodInfo>,\n    pub attrs: Vec<Type>,\n}\n\nimpl ClassFile {\n    pub fn inner_classes(&self) -> Option<Vec<InnerClass>> {\n        for it in self.attrs.iter() {\n            if let Type::InnerClasses { classes } = it {\n                return Some(classes.clone());\n            }\n        }\n\n        None\n    }\n\n    pub fn signature(&self) -> Option<usize> {\n        for it in self.attrs.iter() {\n            if let Type::Signature { signature_index } = it {\n                return Some(*signature_index as usize);\n            }\n        }\n\n        None\n    }\n}\n"
  },
  {
    "path": "crates/classfile/src/constant_pool.rs",
    "content": "use crate::consts::{\n    CONSTANT_INTERFACE_METHOD_REF_TAG, CONSTANT_METHOD_REF_TAG, METHOD_NAME_CLINIT,\n    METHOD_NAME_INIT,\n};\nuse crate::{BytesRef, ConstantPool};\nuse fmt::Debug;\nuse std::fmt;\nuse std::sync::Arc;\n\npub fn get_class_name(cp: &ConstantPool, idx: usize) -> &BytesRef {\n    match cp.get(idx) {\n        Some(Type::Class { name_index }) => get_utf8(cp, *name_index as usize),\n        _ => unreachable!(),\n    }\n}\n\npub fn get_field_ref(cp: &ConstantPool, idx: usize) -> (u16, u16) {\n    match cp.get(idx) {\n        Some(Type::FieldRef {\n            class_index,\n            name_and_type_index,\n        }) => (*class_index, *name_and_type_index),\n        _ => unreachable!(),\n    }\n}\n\npub fn get_method_ref(cp: &ConstantPool, idx: usize) -> (u8, u16, u16) {\n    match cp.get(idx) {\n        Some(Type::MethodRef {\n            class_index,\n            name_and_type_index,\n        }) => (CONSTANT_METHOD_REF_TAG, *class_index, *name_and_type_index),\n        Some(Type::InterfaceMethodRef {\n            class_index,\n            name_and_type_index,\n        }) => (\n            CONSTANT_INTERFACE_METHOD_REF_TAG,\n            *class_index,\n            *name_and_type_index,\n        ),\n        _ => unreachable!(),\n    }\n}\n\npub fn get_name_and_type(cp: &ConstantPool, idx: usize) -> (&BytesRef, &BytesRef) {\n    match cp.get(idx) {\n        Some(Type::NameAndType {\n            name_index,\n            desc_index,\n        }) => (\n            get_utf8(cp, *name_index as usize),\n            get_utf8(cp, *desc_index as usize),\n        ),\n        _ => unreachable!(),\n    }\n}\n\npub fn get_utf8(cp: &ConstantPool, idx: usize) -> &BytesRef {\n    match cp.get(idx) {\n        Some(Type::Utf8 { bytes }) => bytes,\n        _ => unreachable!(),\n    }\n}\n\npub fn get_string(cp: &ConstantPool, idx: usize) -> String {\n    match cp.get(idx) {\n        Some(Type::String { string_index }) => {\n            let v = get_utf8(cp, *string_index as usize);\n            let raw = construct_string_raw(v.as_slice());\n            String::from_utf16_lossy(raw.as_slice())\n        }\n        _ => unreachable!(),\n    }\n}\n\npub fn construct_string_raw(bs: &[u8]) -> Vec<u16> {\n    let length = bs.len();\n    let mut buffer: Vec<u16> = Vec::with_capacity(length);\n    let mut pos = 0;\n    while pos < length {\n        if bs[pos] & 0x80 == 0 {\n            let v = bs[pos] as u16;\n            buffer.push(v);\n            pos += 1;\n        } else if bs[pos] & 0xE0 == 0xC0 && (bs[pos + 1] & 0xC0) == 0x80 {\n            let x = bs[pos] as u16;\n            let y = bs[pos + 1] as u16;\n            let v = ((x & 0x1f) << 6) + (y & 0x3f);\n            buffer.push(v);\n            pos += 2;\n        } else if bs[pos] & 0xF0 == 0xE0\n            && (bs[pos + 1] & 0xC0) == 0x80\n            && (bs[pos + 2] & 0xC0) == 0x80\n        {\n            let x = bs[pos] as u16;\n            let y = bs[pos + 1] as u16;\n            let z = bs[pos + 2] as u16;\n            let v = ((x & 0xf) << 12) + ((y & 0x3f) << 6) + (z & 0x3f);\n            buffer.push(v);\n            pos += 3;\n        } else if bs[pos] == 0xED\n            && (bs[pos + 1] & 0xF0 == 0xA0)\n            && (bs[pos + 2] & 0xC0 == 0x80)\n            && (bs[pos + 3] == 0xED)\n            && (bs[pos + 4] & 0xF0 == 0xB0)\n            && (bs[pos + 5] & 0xC0 == 0x80)\n        {\n            let v = bs[pos + 1] as u32;\n            let w = bs[pos + 2] as u32;\n            let y = bs[pos + 4] as u32;\n            let z = bs[pos + 5] as u32;\n            let vv =\n                0x10000 + ((v & 0x0f) << 16) + ((w & 0x3f) << 10) + ((y & 0x0f) << 6) + (z & 0x3f);\n            buffer.push(vv as u16);\n\n            pos += 6;\n        } else {\n            unreachable!()\n        }\n    }\n\n    buffer\n}\n\n#[derive(Debug, Clone)]\npub enum Type {\n    Nop,\n    Class {\n        name_index: u16,\n    },\n    FieldRef {\n        class_index: u16,\n        name_and_type_index: u16,\n    },\n    MethodRef {\n        class_index: u16,\n        name_and_type_index: u16,\n    },\n    InterfaceMethodRef {\n        class_index: u16,\n        name_and_type_index: u16,\n    },\n    String {\n        string_index: u16,\n    },\n    Integer {\n        v: [u8; 4],\n    },\n    Float {\n        v: [u8; 4],\n    },\n    Long {\n        v: [u8; 8],\n    },\n    Double {\n        v: [u8; 8],\n    },\n    NameAndType {\n        name_index: u16,\n        desc_index: u16,\n    },\n    Utf8 {\n        bytes: BytesRef,\n    },\n    MethodHandle {\n        ref_kind: u8,\n        ref_index: u16,\n    },\n    MethodType {\n        desc_index: u16,\n    },\n    InvokeDynamic {\n        bootstrap_method_attr_index: u16,\n        name_and_type_index: u16,\n    },\n    Unknown,\n}\n\n#[derive(Debug, Clone, Copy)]\npub enum Tag {\n    Class,\n    FieldRef,\n    MethodRef,\n    InterfaceMethodRef,\n    String,\n    Integer,\n    Float,\n    Long,\n    Double,\n    NameAndType,\n    Utf8,\n    MethodHandle,\n    MethodType,\n    InvokeDynamic,\n}\n\nimpl From<u8> for Tag {\n    fn from(tag: u8) -> Self {\n        match tag {\n            7 => Tag::Class,\n            9 => Tag::FieldRef,\n            10 => Tag::MethodRef,\n            11 => Tag::InterfaceMethodRef,\n            8 => Tag::String,\n            3 => Tag::Integer,\n            4 => Tag::Float,\n            5 => Tag::Long,\n            6 => Tag::Double,\n            12 => Tag::NameAndType,\n            1 => Tag::Utf8,\n            15 => Tag::MethodHandle,\n            16 => Tag::MethodType,\n            18 => Tag::InvokeDynamic,\n            _ => unreachable!(),\n        }\n    }\n}\n\nimpl Type {\n    pub fn as_cp_item<'a, 'b>(&'a self, cp: &'b ConstantPool) -> ConstantPoolItem<'a, 'b> {\n        ConstantPoolItem { cp, item: self }\n    }\n}\n\npub struct ConstantPoolItem<'item, 'cp> {\n    cp: &'cp ConstantPool,\n    item: &'item Type,\n}\n\nimpl Debug for ConstantPoolItem<'_, '_> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match self.item {\n            Type::Nop => f.debug_struct(\"Nop\").finish(),\n            Type::Class { name_index } => f\n                .debug_struct(\"Class\")\n                .field(\"name_index\", name_index)\n                .field(\n                    \"name\",\n                    &self\n                        .cp\n                        .get(*name_index as usize)\n                        .map(|t| t.as_cp_item(self.cp)),\n                )\n                .finish(),\n            Type::Utf8 { bytes } => f\n                .debug_struct(\"Utf8\")\n                .field(\"string\", &std::str::from_utf8(bytes))\n                .finish(),\n            _ => write!(f, \"TODO debug for: {:?}\", self.item),\n        }\n    }\n}\n"
  },
  {
    "path": "crates/classfile/src/consts.rs",
    "content": "use crate::U4;\n\npub const MAGIC: U4 = 0xCAFEBABE;\n\npub const METHOD_NAME_INIT: &[u8] = b\"<init>\";\npub const METHOD_NAME_CLINIT: &[u8] = b\"<clinit>\";\n\npub const MAX_CP_ENTRIES: u16 = 65535;\npub const MAX_FIELDS_NUM: u16 = 65535;\npub const MAX_METHODS_NUM: u16 = 65535;\npub const MAX_DIRECT_SUPER_INTERFACES_NUM: u16 = 65535;\npub const MAX_LOCAL_VARS_NUM: u16 = 65535;\npub const MAX_OP_STACKS_SIZE: u16 = 65535;\npub const MAX_METHOD_PARAMS_NUM: u16 = 255;\npub const MAX_CONST_STR_LEN: u16 = 65535;\npub const MAX_ARRAY_DIMENSIONS: u16 = 255;\n\npub const J_OBJECT: &[u8] = b\"java/lang/Object\";\npub const J_CLONEABLE: &[u8] = b\"java/lang/Cloneable\";\npub const J_SERIALIZABLE: &[u8] = b\"java/io/Serializable\";\npub const J_CLASS: &[u8] = b\"java/lang/Class\";\npub const J_STRING: &[u8] = b\"java/lang/String\";\npub const J_THREAD: &[u8] = b\"java/lang/Thread\";\npub const J_THREAD_GROUP: &[u8] = b\"java/lang/ThreadGroup\";\npub const J_SYSTEM: &[u8] = b\"java/lang/System\";\n\npub const J_INPUT_STREAM: &[u8] = b\"java/io/InputStream\";\npub const J_PRINT_STREAM: &[u8] = b\"java/io/PrintStream\";\npub const J_SECURITY_MANAGER: &[u8] = b\"java/lang/SecurityManager\";\n\npub const J_FIELD: &[u8] = b\"java/lang/reflect/Field\";\npub const J_METHOD: &[u8] = b\"java/lang/reflect/Method\";\npub const J_METHOD_CTOR: &[u8] = b\"java/lang/reflect/Constructor\";\npub const J_ACCESSIBLE_OBJECT: &[u8] = b\"java/lang/reflect/AccessibleObject\";\npub const J_METHODHANDLE: &[u8] = b\"java/lang/invoke/MethodHandle\";\npub const J_METHODTYPE: &[u8] = b\"java/lang/invoke/MethodType\";\n\npub const J_INTERNAL_ERROR: &[u8] = b\"java/lang/InternalError\";\npub const J_NPE: &[u8] = b\"java/lang/NullPointerException\";\npub const J_IOEXCEPTION: &[u8] = b\"java/io/IOException\";\npub const J_ARRAY_INDEX_OUT_OF_BOUNDS: &[u8] = b\"java/lang/ArrayIndexOutOfBoundsException\";\npub const J_CLASS_NOT_FOUND: &[u8] = b\"java/lang/ClassNotFoundException\";\npub const J_ARITHMETIC_EX: &[u8] = b\"java/lang/ArithmeticException\";\npub const J_SOE: &[u8] = b\"java/lang/StackOverflowError\";\npub const J_NASE: &[u8] = b\"java/lang/NegativeArraySizeException\";\npub const J_CCE: &[u8] = b\"java/lang/ClassCastException\";\npub const J_THROWABLE: &[u8] = b\"java/lang/Throwable\";\n\npub const CONSTANT_METHOD_REF_TAG: u8 = 10;\npub const CONSTANT_INTERFACE_METHOD_REF_TAG: u8 = 11;\n"
  },
  {
    "path": "crates/classfile/src/field_info.rs",
    "content": "use crate::attributes::Type;\nuse crate::U2;\n\n#[derive(Debug)]\npub struct FieldInfo {\n    pub acc_flags: U2,\n    pub name_index: U2,\n    pub desc_index: U2,\n    pub attrs: Vec<Type>,\n}\n"
  },
  {
    "path": "crates/classfile/src/flags.rs",
    "content": "use crate::U2;\n\nmacro_rules! def_acc {\n    ($name:ident, $v:expr) => {\n        pub const $name: U2 = $v;\n    };\n}\n\ndef_acc!(ACC_PUBLIC, 0x0001);\ndef_acc!(ACC_PRIVATE, 0x0002);\ndef_acc!(ACC_PROTECTED, 0x0004);\ndef_acc!(ACC_STATIC, 0x0008);\ndef_acc!(ACC_FINAL, 0x0010);\ndef_acc!(ACC_SYNCHRONIZED, 0x0020);\ndef_acc!(ACC_SUPER, 0x0020);\ndef_acc!(ACC_VOLATILE, 0x0040);\ndef_acc!(ACC_BRIDGE, 0x0040);\ndef_acc!(ACC_VARARGS, 0x0080);\ndef_acc!(ACC_TRANSIENT, 0x0080);\ndef_acc!(ACC_NATIVE, 0x0100);\ndef_acc!(ACC_INTERFACE, 0x0200);\ndef_acc!(ACC_ABSTRACT, 0x0400);\ndef_acc!(ACC_STRICT, 0x0800);\ndef_acc!(ACC_SYNTHETIC, 0x1000);\ndef_acc!(ACC_ANNOTATION, 0x2000);\ndef_acc!(ACC_ENUM, 0x4000);\ndef_acc!(ACC_MIRANDA, 0x8000);\ndef_acc!(ACC_REFLECT_MASK, 0xffff);\n"
  },
  {
    "path": "crates/classfile/src/lib.rs",
    "content": "#![allow(unused)]\n\n//! Provides types for working with class file.\n//!\n//! The `classfile` crate provides types for describing the\n//! class file format of the Java Virtual Machine.\n//!\n//! It's not class file parser.\n#[macro_use]\nextern crate lazy_static;\n#[macro_use]\nextern crate log;\npub mod attributes;\nmod classfile;\npub mod constant_pool;\npub mod consts;\nmod field_info;\npub mod flags;\nmod method_info;\nmod opcode;\nmod signature;\nmod version;\n\npub type U1 = u8;\npub type U2 = u16;\npub type U4 = u32;\npub type BytesRef = std::sync::Arc<Vec<u8>>;\npub type ConstantPool = std::sync::Arc<Vec<constant_pool::Type>>;\n\npub use crate::classfile::ClassFile;\npub use attributes::Type as AttributeType;\npub use constant_pool::Type as ConstantPoolType;\npub use field_info::FieldInfo;\npub use method_info::MethodInfo;\npub use opcode::OpCode;\npub use signature::Type as SignatureType;\npub use version::Version;\n"
  },
  {
    "path": "crates/classfile/src/method_info.rs",
    "content": "use crate::attributes::{Code, CodeException, LineNumber, LocalVariable, StackMapFrame, Type};\nuse crate::constant_pool;\nuse crate::{BytesRef, ConstantPool, U2};\nuse std::collections::HashMap;\n\n#[derive(Debug, Clone)]\npub struct MethodInfo {\n    pub acc_flags: U2,\n    pub name_index: U2,\n    pub desc_index: U2,\n    pub attrs: Vec<Type>,\n}\n\nimpl MethodInfo {\n    pub fn get_code(&self) -> Option<Code> {\n        for it in self.attrs.iter() {\n            if let Type::Code(code) = it {\n                return Some(code.clone());\n            }\n        }\n\n        None\n    }\n\n    pub fn get_line_number_table(&self) -> Vec<LineNumber> {\n        let mut line_num_table = Vec::new();\n\n        self.attrs.iter().for_each(|attr| {\n            if let Type::Code(code) = attr {\n                code.attrs.iter().for_each(|it| {\n                    if let Type::LineNumberTable { tables } = it {\n                        line_num_table.extend_from_slice(tables.as_slice());\n                    }\n                });\n            }\n        });\n\n        line_num_table\n    }\n\n    pub fn get_throws(&self) -> Option<Vec<U2>> {\n        for it in self.attrs.iter() {\n            if let Type::Exceptions { exceptions } = it {\n                return Some(exceptions.clone());\n            }\n        }\n\n        None\n    }\n\n    pub fn get_ex_table(&self) -> Option<Vec<CodeException>> {\n        for it in self.attrs.iter() {\n            if let Type::Code(code) = it {\n                if !code.exceptions.is_empty() {\n                    return Some(code.exceptions.clone());\n                }\n            }\n        }\n\n        None\n    }\n\n    pub fn get_stack_map_table(&self) -> Option<Vec<StackMapFrame>> {\n        if let Some(code) = self.get_code() {\n            for it in code.attrs.iter() {\n                if let Type::StackMapTable { entries } = it {\n                    return Some(entries.clone());\n                }\n            }\n        }\n\n        None\n    }\n\n    pub fn get_local_variable_table(&self) -> Option<Vec<LocalVariable>> {\n        if let Some(code) = self.get_code() {\n            for it in code.attrs.iter() {\n                if let Type::LocalVariableTable { tables } = it {\n                    return Some(tables.clone());\n                }\n            }\n        }\n\n        None\n    }\n\n    pub fn get_local_variable_type_table(&self) -> Option<Vec<LocalVariable>> {\n        if let Some(code) = self.get_code() {\n            for it in code.attrs.iter() {\n                if let Type::LocalVariableTypeTable { tables } = it {\n                    return Some(tables.clone());\n                }\n            }\n        }\n\n        None\n    }\n}\n"
  },
  {
    "path": "crates/classfile/src/opcode.rs",
    "content": "#![allow(non_camel_case_types)]\n\n#[repr(u8)]\n#[derive(Debug, PartialEq, Eq, Copy, Clone)]\npub enum OpCode {\n    //Constants\n    nop,\n    aconst_null,\n    iconst_m1,\n    iconst_0,\n    iconst_1,\n    iconst_2,\n    iconst_3,\n    iconst_4,\n    iconst_5,\n    lconst_0,\n    lconst_1,\n    fconst_0,\n    fconst_1,\n    fconst_2,\n    dconst_0,\n    dconst_1,\n    bipush,\n    sipush,\n    ldc,\n    ldc_w,\n    ldc2_w,\n    //Loads\n    iload,\n    lload,\n    fload,\n    dload,\n    aload,\n    iload_0,\n    iload_1,\n    iload_2,\n    iload_3,\n    lload_0,\n    lload_1,\n    lload_2,\n    lload_3,\n    fload_0,\n    fload_1,\n    fload_2,\n    fload_3,\n    dload_0,\n    dload_1,\n    dload_2,\n    dload_3,\n    aload_0,\n    aload_1,\n    aload_2,\n    aload_3,\n    iaload,\n    laload,\n    faload,\n    daload,\n    aaload,\n    baload,\n    caload,\n    saload,\n    //Stores\n    istore,\n    lstore,\n    fstore,\n    dstore,\n    astore,\n    istore_0,\n    istore_1,\n    istore_2,\n    istore_3,\n    lstore_0,\n    lstore_1,\n    lstore_2,\n    lstore_3,\n    fstore_0,\n    fstore_1,\n    fstore_2,\n    fstore_3,\n    dstore_0,\n    dstore_1,\n    dstore_2,\n    dstore_3,\n    astore_0,\n    astore_1,\n    astore_2,\n    astore_3,\n    iastore,\n    lastore,\n    fastore,\n    dastore,\n    aastore,\n    bastore,\n    castore,\n    sastore,\n    //Stack\n    pop,\n    pop2,\n    dup,\n    dup_x1,\n    dup_x2,\n    dup2,\n    dup2_x1,\n    dup2_x2,\n    swap,\n    //Math\n    iadd,\n    ladd,\n    fadd,\n    dadd,\n    isub,\n    lsub,\n    fsub,\n    dsub,\n    imul,\n    lmul,\n    fmul,\n    dmul,\n    idiv,\n    ldiv,\n    fdiv,\n    ddiv,\n    irem,\n    lrem,\n    frem, //deprecated\n    drem, //deprecated\n    ineg,\n    lneg,\n    fneg, //deprecated\n    dneg, //deprecated\n    ishl,\n    lshl,\n    ishr,\n    lshr,\n    iushr,\n    lushr,\n    iand,\n    land,\n    ior,\n    lor,\n    ixor,\n    lxor,\n    iinc,\n    //Conversions\n    i2l,\n    i2f,\n    i2d,\n    l2i,\n    l2f,\n    l2d,\n    f2i,\n    f2l,\n    f2d,\n    d2i,\n    d2l,\n    d2f,\n    i2b,\n    i2c,\n    i2s,\n    //Comparisons\n    lcmp,\n    fcmpl,\n    fcmpg,\n    dcmpl,\n    dcmpg,\n    ifeq,\n    ifne,\n    iflt,\n    ifge,\n    ifgt,\n    ifle,\n    if_icmpeq,\n    if_icmpne,\n    if_icmplt,\n    if_icmpge,\n    if_icmpgt,\n    if_icmple,\n    if_acmpeq,\n    if_acmpne,\n    //Control\n    goto,\n    jsr, //deprecated\n    ret, //deprecated\n    tableswitch,\n    lookupswitch,\n    ireturn,\n    lreturn,\n    freturn,\n    dreturn,\n    areturn,\n    return_void,\n    //References\n    getstatic,\n    putstatic,\n    getfield,\n    putfield,\n    invokevirtual,\n    invokespecial,\n    invokestatic,\n    invokeinterface,\n    invokedynamic,\n    new,\n    newarray,\n    anewarray,\n    arraylength,\n    athrow,\n    checkcast,\n    instanceof,\n    monitorenter,\n    monitorexit,\n    //Extended\n    wide, //deprecated\n    multianewarray,\n    ifnull,\n    ifnonnull,\n    goto_w, //deprecated\n    jsr_w,  //deprecated\n    reserved,\n    breakpoint,\n    impdep1,\n    impdep2,\n}\n\nimpl From<u8> for OpCode {\n    #[inline]\n    fn from(v: u8) -> Self {\n        match v {\n            0 => OpCode::nop,\n            1 => OpCode::aconst_null,\n            2 => OpCode::iconst_m1,\n            3 => OpCode::iconst_0,\n            4 => OpCode::iconst_1,\n            5 => OpCode::iconst_2,\n            6 => OpCode::iconst_3,\n            7 => OpCode::iconst_4,\n            8 => OpCode::iconst_5,\n            9 => OpCode::lconst_0,\n            10 => OpCode::lconst_1,\n            11 => OpCode::fconst_0,\n            12 => OpCode::fconst_1,\n            13 => OpCode::fconst_2,\n            14 => OpCode::dconst_0,\n            15 => OpCode::dconst_1,\n            16 => OpCode::bipush,\n            17 => OpCode::sipush,\n            18 => OpCode::ldc,\n            19 => OpCode::ldc_w,\n            20 => OpCode::ldc2_w,\n            21 => OpCode::iload,\n            22 => OpCode::lload,\n            23 => OpCode::fload,\n            24 => OpCode::dload,\n            25 => OpCode::aload,\n            26 => OpCode::iload_0,\n            27 => OpCode::iload_1,\n            28 => OpCode::iload_2,\n            29 => OpCode::iload_3,\n            30 => OpCode::lload_0,\n            31 => OpCode::lload_1,\n            32 => OpCode::lload_2,\n            33 => OpCode::lload_3,\n            34 => OpCode::fload_0,\n            35 => OpCode::fload_1,\n            36 => OpCode::fload_2,\n            37 => OpCode::fload_3,\n            38 => OpCode::dload_0,\n            39 => OpCode::dload_1,\n            40 => OpCode::dload_2,\n            41 => OpCode::dload_3,\n            42 => OpCode::aload_0,\n            43 => OpCode::aload_1,\n            44 => OpCode::aload_2,\n            45 => OpCode::aload_3,\n            46 => OpCode::iaload,\n            47 => OpCode::laload,\n            48 => OpCode::faload,\n            49 => OpCode::daload,\n            50 => OpCode::aaload,\n            51 => OpCode::baload,\n            52 => OpCode::caload,\n            53 => OpCode::saload,\n            54 => OpCode::istore,\n            55 => OpCode::lstore,\n            56 => OpCode::fstore,\n            57 => OpCode::dstore,\n            58 => OpCode::astore,\n            59 => OpCode::istore_0,\n            60 => OpCode::istore_1,\n            61 => OpCode::istore_2,\n            62 => OpCode::istore_3,\n            63 => OpCode::lstore_0,\n            64 => OpCode::lstore_1,\n            65 => OpCode::lstore_2,\n            66 => OpCode::lstore_3,\n            67 => OpCode::fstore_0,\n            68 => OpCode::fstore_1,\n            69 => OpCode::fstore_2,\n            70 => OpCode::fstore_3,\n            71 => OpCode::dstore_0,\n            72 => OpCode::dstore_1,\n            73 => OpCode::dstore_2,\n            74 => OpCode::dstore_3,\n            75 => OpCode::astore_0,\n            76 => OpCode::astore_1,\n            77 => OpCode::astore_2,\n            78 => OpCode::astore_3,\n            79 => OpCode::iastore,\n            80 => OpCode::lastore,\n            81 => OpCode::fastore,\n            82 => OpCode::dastore,\n            83 => OpCode::aastore,\n            84 => OpCode::bastore,\n            85 => OpCode::castore,\n            86 => OpCode::sastore,\n            87 => OpCode::pop,\n            88 => OpCode::pop2,\n            89 => OpCode::dup,\n            90 => OpCode::dup_x1,\n            91 => OpCode::dup_x2,\n            92 => OpCode::dup2,\n            93 => OpCode::dup2_x1,\n            94 => OpCode::dup_x2,\n            95 => OpCode::swap,\n            96 => OpCode::iadd,\n            97 => OpCode::ladd,\n            98 => OpCode::fadd,\n            99 => OpCode::dadd,\n            100 => OpCode::isub,\n            101 => OpCode::lsub,\n            102 => OpCode::fsub,\n            103 => OpCode::dsub,\n            104 => OpCode::imul,\n            105 => OpCode::lmul,\n            106 => OpCode::fmul,\n            107 => OpCode::dmul,\n            108 => OpCode::idiv,\n            109 => OpCode::ldiv,\n            110 => OpCode::fdiv,\n            111 => OpCode::ddiv,\n            112 => OpCode::irem,\n            113 => OpCode::lrem,\n            114 => OpCode::frem,\n            115 => OpCode::drem,\n            116 => OpCode::ineg,\n            117 => OpCode::lneg,\n            118 => OpCode::fneg,\n            119 => OpCode::dneg,\n            120 => OpCode::ishl,\n            121 => OpCode::lshl,\n            122 => OpCode::ishr,\n            123 => OpCode::lshr,\n            124 => OpCode::iushr,\n            125 => OpCode::lushr,\n            126 => OpCode::iand,\n            127 => OpCode::land,\n            128 => OpCode::ior,\n            129 => OpCode::lor,\n            130 => OpCode::ixor,\n            131 => OpCode::lxor,\n            132 => OpCode::iinc,\n            133 => OpCode::i2l,\n            134 => OpCode::i2f,\n            135 => OpCode::i2d,\n            136 => OpCode::l2i,\n            137 => OpCode::l2f,\n            138 => OpCode::l2d,\n            139 => OpCode::f2i,\n            140 => OpCode::f2l,\n            141 => OpCode::f2d,\n            142 => OpCode::d2i,\n            143 => OpCode::d2l,\n            144 => OpCode::d2f,\n            145 => OpCode::i2b,\n            146 => OpCode::i2c,\n            147 => OpCode::i2s,\n            148 => OpCode::lcmp,\n            149 => OpCode::fcmpl,\n            150 => OpCode::fcmpg,\n            151 => OpCode::dcmpl,\n            152 => OpCode::dcmpg,\n            153 => OpCode::ifeq,\n            154 => OpCode::ifne,\n            155 => OpCode::iflt,\n            156 => OpCode::ifge,\n            157 => OpCode::ifgt,\n            158 => OpCode::ifle,\n            159 => OpCode::if_icmpeq,\n            160 => OpCode::if_icmpne,\n            161 => OpCode::if_icmplt,\n            162 => OpCode::if_icmpge,\n            163 => OpCode::if_icmpgt,\n            164 => OpCode::if_icmple,\n            165 => OpCode::if_acmpeq,\n            166 => OpCode::if_acmpne,\n            167 => OpCode::goto,\n            168 => OpCode::jsr,\n            169 => OpCode::ret,\n            170 => OpCode::tableswitch,\n            171 => OpCode::lookupswitch,\n            172 => OpCode::ireturn,\n            173 => OpCode::lreturn,\n            174 => OpCode::freturn,\n            175 => OpCode::dreturn,\n            176 => OpCode::areturn,\n            177 => OpCode::return_void,\n            178 => OpCode::getstatic,\n            179 => OpCode::putstatic,\n            180 => OpCode::getfield,\n            181 => OpCode::putfield,\n            182 => OpCode::invokevirtual,\n            183 => OpCode::invokespecial,\n            184 => OpCode::invokestatic,\n            185 => OpCode::invokeinterface,\n            186 => OpCode::invokedynamic,\n            187 => OpCode::new,\n            188 => OpCode::newarray,\n            189 => OpCode::anewarray,\n            190 => OpCode::arraylength,\n            191 => OpCode::athrow,\n            192 => OpCode::checkcast,\n            193 => OpCode::instanceof,\n            194 => OpCode::monitorenter,\n            195 => OpCode::monitorexit,\n            196 => OpCode::wide,\n            197 => OpCode::multianewarray,\n            198 => OpCode::ifnull,\n            199 => OpCode::ifnonnull,\n            200 => OpCode::goto_w,\n            201 => OpCode::jsr_w,\n            202 => OpCode::breakpoint,\n            254 => OpCode::impdep1,\n            255 => OpCode::impdep2,\n            _ => OpCode::reserved,\n        }\n    }\n}\n\nimpl Into<&'static str> for OpCode {\n    fn into(self) -> &'static str {\n        match self {\n            OpCode::nop => \"nop\",\n            OpCode::aconst_null => \"aconst_null\",\n            OpCode::iconst_m1 => \"iconst_m1\",\n            OpCode::iconst_0 => \"iconst_0\",\n            OpCode::iconst_1 => \"iconst_1\",\n            OpCode::iconst_2 => \"iconst_2\",\n            OpCode::iconst_3 => \"iconst_3\",\n            OpCode::iconst_4 => \"iconst_4\",\n            OpCode::iconst_5 => \"iconst_5\",\n            OpCode::lconst_0 => \"lconst_0\",\n            OpCode::lconst_1 => \"lconst_1\",\n            OpCode::fconst_0 => \"fconst_0\",\n            OpCode::fconst_1 => \"fconst_1\",\n            OpCode::fconst_2 => \"fconst_2\",\n            OpCode::dconst_0 => \"dconst_0\",\n            OpCode::dconst_1 => \"dconst_1\",\n            OpCode::bipush => \"bipush\",\n            OpCode::sipush => \"sipush\",\n            OpCode::ldc => \"ldc\",\n            OpCode::ldc_w => \"ldc_w\",\n            OpCode::ldc2_w => \"ldc2_w\",\n            OpCode::iload => \"iload\",\n            OpCode::lload => \"lload\",\n            OpCode::fload => \"fload\",\n            OpCode::dload => \"dload\",\n            OpCode::aload => \"aload\",\n            OpCode::iload_0 => \"iload_0\",\n            OpCode::iload_1 => \"iload_1\",\n            OpCode::iload_2 => \"iload_2\",\n            OpCode::iload_3 => \"iload_3\",\n            OpCode::lload_0 => \"lload_0\",\n            OpCode::lload_1 => \"lload_1\",\n            OpCode::lload_2 => \"lload_2\",\n            OpCode::lload_3 => \"lload_3\",\n            OpCode::fload_0 => \"fload_0\",\n            OpCode::fload_1 => \"fload_1\",\n            OpCode::fload_2 => \"fload_2\",\n            OpCode::fload_3 => \"fload_3\",\n            OpCode::dload_0 => \"dload_0\",\n            OpCode::dload_1 => \"dload_1\",\n            OpCode::dload_2 => \"dload_2\",\n            OpCode::dload_3 => \"dload_3\",\n            OpCode::aload_0 => \"aload_0\",\n            OpCode::aload_1 => \"aload_1\",\n            OpCode::aload_2 => \"aload_2\",\n            OpCode::aload_3 => \"aload_3\",\n            OpCode::iaload => \"iaload\",\n            OpCode::laload => \"laload\",\n            OpCode::faload => \"faload\",\n            OpCode::daload => \"daload\",\n            OpCode::aaload => \"aaload\",\n            OpCode::baload => \"baload\",\n            OpCode::caload => \"caload\",\n            OpCode::saload => \"saload\",\n            OpCode::istore => \"istore\",\n            OpCode::lstore => \"lstore\",\n            OpCode::fstore => \"fstore\",\n            OpCode::dstore => \"dstore\",\n            OpCode::astore => \"astore\",\n            OpCode::istore_0 => \"istore_0\",\n            OpCode::istore_1 => \"istore_1\",\n            OpCode::istore_2 => \"istore_2\",\n            OpCode::istore_3 => \"istore_3\",\n            OpCode::lstore_0 => \"lstore_0\",\n            OpCode::lstore_1 => \"lstore_1\",\n            OpCode::lstore_2 => \"lstore_2\",\n            OpCode::lstore_3 => \"lstore_3\",\n            OpCode::fstore_0 => \"fstore_0\",\n            OpCode::fstore_1 => \"fstore_1\",\n            OpCode::fstore_2 => \"fstore_2\",\n            OpCode::fstore_3 => \"fstore_3\",\n            OpCode::dstore_0 => \"dstore_0\",\n            OpCode::dstore_1 => \"dstore_1\",\n            OpCode::dstore_2 => \"dstore_2\",\n            OpCode::dstore_3 => \"dstore_3\",\n            OpCode::astore_0 => \"astore_0\",\n            OpCode::astore_1 => \"astore_1\",\n            OpCode::astore_2 => \"astore_2\",\n            OpCode::astore_3 => \"astore_3\",\n            OpCode::iastore => \"iastore\",\n            OpCode::lastore => \"lastore\",\n            OpCode::fastore => \"fastore\",\n            OpCode::dastore => \"dastore\",\n            OpCode::aastore => \"aastore\",\n            OpCode::bastore => \"bastore\",\n            OpCode::castore => \"castore\",\n            OpCode::sastore => \"sastore\",\n            OpCode::pop => \"pop\",\n            OpCode::pop2 => \"pop2\",\n            OpCode::dup => \"dup\",\n            OpCode::dup_x1 => \"dup_x1\",\n            OpCode::dup_x2 => \"dup_x2\",\n            OpCode::dup2 => \"dup2\",\n            OpCode::dup2_x1 => \"dup2_x1\",\n            OpCode::dup2_x2 => \"dup2_x2\",\n            OpCode::swap => \"swap\",\n            OpCode::iadd => \"iadd\",\n            OpCode::ladd => \"ladd\",\n            OpCode::fadd => \"fadd\",\n            OpCode::dadd => \"dadd\",\n            OpCode::isub => \"isub\",\n            OpCode::lsub => \"lsub\",\n            OpCode::fsub => \"fsub\",\n            OpCode::dsub => \"dsub\",\n            OpCode::imul => \"imul\",\n            OpCode::lmul => \"lmul\",\n            OpCode::fmul => \"fmul\",\n            OpCode::dmul => \"dmul\",\n            OpCode::idiv => \"idiv\",\n            OpCode::ldiv => \"ldiv\",\n            OpCode::fdiv => \"fdiv\",\n            OpCode::ddiv => \"ddiv\",\n            OpCode::irem => \"irem\",\n            OpCode::lrem => \"lrem\",\n            OpCode::frem => \"frem\",\n            OpCode::drem => \"drem\",\n            OpCode::ineg => \"ineg\",\n            OpCode::lneg => \"lneg\",\n            OpCode::fneg => \"fneg\",\n            OpCode::dneg => \"dneg\",\n            OpCode::ishl => \"ishl\",\n            OpCode::lshl => \"lshl\",\n            OpCode::ishr => \"ishr\",\n            OpCode::lshr => \"lshr\",\n            OpCode::iushr => \"iushr\",\n            OpCode::lushr => \"lushr\",\n            OpCode::iand => \"iand\",\n            OpCode::land => \"land\",\n            OpCode::ior => \"ior\",\n            OpCode::lor => \"lor\",\n            OpCode::ixor => \"ixor\",\n            OpCode::lxor => \"lxor\",\n            OpCode::iinc => \"iinc\",\n            OpCode::i2l => \"i2l\",\n            OpCode::i2f => \"i2f\",\n            OpCode::i2d => \"i2d\",\n            OpCode::l2i => \"l2i\",\n            OpCode::l2f => \"l2f\",\n            OpCode::l2d => \"l2d\",\n            OpCode::f2i => \"f2i\",\n            OpCode::f2l => \"f2l\",\n            OpCode::f2d => \"f2d\",\n            OpCode::d2i => \"d2i\",\n            OpCode::d2l => \"d2l\",\n            OpCode::d2f => \"d2f\",\n            OpCode::i2b => \"i2b\",\n            OpCode::i2c => \"i2c\",\n            OpCode::i2s => \"i2s\",\n            OpCode::lcmp => \"lcmp\",\n            OpCode::fcmpl => \"fcmpl\",\n            OpCode::fcmpg => \"fcmpg\",\n            OpCode::dcmpl => \"dcmpl\",\n            OpCode::dcmpg => \"dcmpg\",\n            OpCode::ifeq => \"ifeq\",\n            OpCode::ifne => \"ifne\",\n            OpCode::iflt => \"iflt\",\n            OpCode::ifge => \"ifge\",\n            OpCode::ifgt => \"ifgt\",\n            OpCode::ifle => \"ifle\",\n            OpCode::if_icmpeq => \"if_icmpeq\",\n            OpCode::if_icmpne => \"if_icmpne\",\n            OpCode::if_icmplt => \"if_icmplt\",\n            OpCode::if_icmpge => \"if_icmpge\",\n            OpCode::if_icmpgt => \"if_icmpgt\",\n            OpCode::if_icmple => \"if_icmple\",\n            OpCode::if_acmpeq => \"if_acmpeq\",\n            OpCode::if_acmpne => \"if_acmpne\",\n            OpCode::goto => \"goto\",\n            OpCode::jsr => \"jsr\",\n            OpCode::ret => \"ret\",\n            OpCode::tableswitch => \"tableswitch\",\n            OpCode::lookupswitch => \"lookupswitch\",\n            OpCode::ireturn => \"ireturn\",\n            OpCode::lreturn => \"lreturn\",\n            OpCode::freturn => \"freturn\",\n            OpCode::dreturn => \"dreturn\",\n            OpCode::areturn => \"areturn\",\n            OpCode::return_void => \"return\",\n            OpCode::getstatic => \"getstatic\",\n            OpCode::putstatic => \"putstatic\",\n            OpCode::getfield => \"getfield\",\n            OpCode::putfield => \"putfield\",\n            OpCode::invokevirtual => \"invokevirtual\",\n            OpCode::invokespecial => \"invokespecial\",\n            OpCode::invokestatic => \"invokestatic\",\n            OpCode::invokeinterface => \"invokeinterface\",\n            OpCode::invokedynamic => \"invokedynamic\",\n            OpCode::new => \"new\",\n            OpCode::newarray => \"newarray\",\n            OpCode::anewarray => \"anewarray\",\n            OpCode::arraylength => \"arraylength\",\n            OpCode::athrow => \"athrow\",\n            OpCode::checkcast => \"checkcast\",\n            OpCode::instanceof => \"instanceof\",\n            OpCode::monitorenter => \"monitorenter\",\n            OpCode::monitorexit => \"monitorexit\",\n            OpCode::wide => \"wide\",\n            OpCode::multianewarray => \"multianewarray\",\n            OpCode::ifnull => \"ifnull\",\n            OpCode::ifnonnull => \"ifnonnull\",\n            OpCode::goto_w => \"goto_w\",\n            OpCode::jsr_w => \"jsr_w\",\n            _ => unreachable!(),\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::OpCode;\n\n    #[test]\n    fn t_opcode() {\n        assert_eq!(OpCode::nop, OpCode::from(0));\n        assert_eq!(OpCode::aconst_null, OpCode::from(1));\n        assert_eq!(OpCode::iconst_m1, OpCode::from(2));\n        assert_eq!(OpCode::iconst_0, OpCode::from(3));\n        assert_eq!(OpCode::iconst_1, OpCode::from(4));\n        assert_eq!(OpCode::iconst_2, OpCode::from(5));\n        assert_eq!(OpCode::iconst_3, OpCode::from(6));\n        assert_eq!(OpCode::iconst_4, OpCode::from(7));\n        assert_eq!(OpCode::iconst_5, OpCode::from(8));\n        assert_eq!(OpCode::lconst_0, OpCode::from(9));\n        assert_eq!(OpCode::lconst_1, OpCode::from(10));\n        assert_eq!(OpCode::fconst_0, OpCode::from(11));\n        assert_eq!(OpCode::fconst_1, OpCode::from(12));\n        assert_eq!(OpCode::fconst_2, OpCode::from(13));\n        assert_eq!(OpCode::dconst_0, OpCode::from(14));\n        assert_eq!(OpCode::dconst_1, OpCode::from(15));\n        assert_eq!(OpCode::bipush, OpCode::from(16));\n        assert_eq!(OpCode::sipush, OpCode::from(17));\n        assert_eq!(OpCode::ldc, OpCode::from(18));\n        assert_eq!(OpCode::ldc_w, OpCode::from(19));\n        assert_eq!(OpCode::ldc2_w, OpCode::from(20));\n        assert_eq!(OpCode::iload, OpCode::from(21));\n        assert_eq!(OpCode::lload, OpCode::from(22));\n        assert_eq!(OpCode::fload, OpCode::from(23));\n        assert_eq!(OpCode::dload, OpCode::from(24));\n        assert_eq!(OpCode::aload, OpCode::from(25));\n        assert_eq!(OpCode::iload_0, OpCode::from(26));\n        assert_eq!(OpCode::iload_1, OpCode::from(27));\n        assert_eq!(OpCode::iload_2, OpCode::from(28));\n        assert_eq!(OpCode::iload_3, OpCode::from(29));\n        assert_eq!(OpCode::lload_0, OpCode::from(30));\n        assert_eq!(OpCode::lload_1, OpCode::from(31));\n        assert_eq!(OpCode::lload_2, OpCode::from(32));\n        assert_eq!(OpCode::lload_3, OpCode::from(33));\n        assert_eq!(OpCode::fload_0, OpCode::from(34));\n        assert_eq!(OpCode::fload_1, OpCode::from(35));\n        assert_eq!(OpCode::fload_2, OpCode::from(36));\n        assert_eq!(OpCode::fload_3, OpCode::from(37));\n        assert_eq!(OpCode::dload_0, OpCode::from(38));\n        assert_eq!(OpCode::dload_1, OpCode::from(39));\n        assert_eq!(OpCode::dload_2, OpCode::from(40));\n        assert_eq!(OpCode::dload_3, OpCode::from(41));\n        assert_eq!(OpCode::aload_0, OpCode::from(42));\n        assert_eq!(OpCode::aload_1, OpCode::from(43));\n        assert_eq!(OpCode::aload_2, OpCode::from(44));\n        assert_eq!(OpCode::aload_3, OpCode::from(45));\n        assert_eq!(OpCode::iaload, OpCode::from(46));\n        assert_eq!(OpCode::laload, OpCode::from(47));\n        assert_eq!(OpCode::faload, OpCode::from(48));\n        assert_eq!(OpCode::daload, OpCode::from(49));\n        assert_eq!(OpCode::aaload, OpCode::from(50));\n        assert_eq!(OpCode::baload, OpCode::from(51));\n        assert_eq!(OpCode::caload, OpCode::from(52));\n        assert_eq!(OpCode::saload, OpCode::from(53));\n        assert_eq!(OpCode::istore, OpCode::from(54));\n        assert_eq!(OpCode::lstore, OpCode::from(55));\n        assert_eq!(OpCode::fstore, OpCode::from(56));\n        assert_eq!(OpCode::dstore, OpCode::from(57));\n        assert_eq!(OpCode::astore, OpCode::from(58));\n        assert_eq!(OpCode::istore_0, OpCode::from(59));\n        assert_eq!(OpCode::istore_1, OpCode::from(60));\n        assert_eq!(OpCode::istore_2, OpCode::from(61));\n        assert_eq!(OpCode::istore_3, OpCode::from(62));\n        assert_eq!(OpCode::lstore_0, OpCode::from(63));\n        assert_eq!(OpCode::lstore_1, OpCode::from(64));\n        assert_eq!(OpCode::lstore_2, OpCode::from(65));\n        assert_eq!(OpCode::lstore_3, OpCode::from(66));\n        assert_eq!(OpCode::fstore_0, OpCode::from(67));\n        assert_eq!(OpCode::fstore_1, OpCode::from(68));\n        assert_eq!(OpCode::fstore_2, OpCode::from(69));\n        assert_eq!(OpCode::fstore_3, OpCode::from(70));\n        assert_eq!(OpCode::dstore_0, OpCode::from(71));\n        assert_eq!(OpCode::dstore_1, OpCode::from(72));\n        assert_eq!(OpCode::dstore_2, OpCode::from(73));\n        assert_eq!(OpCode::dstore_3, OpCode::from(74));\n        assert_eq!(OpCode::astore_0, OpCode::from(75));\n        assert_eq!(OpCode::astore_1, OpCode::from(76));\n        assert_eq!(OpCode::astore_2, OpCode::from(77));\n        assert_eq!(OpCode::astore_3, OpCode::from(78));\n        assert_eq!(OpCode::iastore, OpCode::from(79));\n        assert_eq!(OpCode::lastore, OpCode::from(80));\n        assert_eq!(OpCode::fastore, OpCode::from(81));\n        assert_eq!(OpCode::dastore, OpCode::from(82));\n        assert_eq!(OpCode::aastore, OpCode::from(83));\n        assert_eq!(OpCode::bastore, OpCode::from(84));\n        assert_eq!(OpCode::castore, OpCode::from(85));\n        assert_eq!(OpCode::sastore, OpCode::from(86));\n        assert_eq!(OpCode::pop, OpCode::from(87));\n        assert_eq!(OpCode::pop2, OpCode::from(88));\n        assert_eq!(OpCode::dup, OpCode::from(89));\n        assert_eq!(OpCode::dup_x1, OpCode::from(90));\n        assert_eq!(OpCode::dup_x2, OpCode::from(91));\n        assert_eq!(OpCode::dup2, OpCode::from(92));\n        assert_eq!(OpCode::dup2_x1, OpCode::from(93));\n        assert_eq!(OpCode::dup2_x2, OpCode::from(94));\n        assert_eq!(OpCode::swap, OpCode::from(95));\n        assert_eq!(OpCode::iadd, OpCode::from(96));\n        assert_eq!(OpCode::ladd, OpCode::from(97));\n        assert_eq!(OpCode::fadd, OpCode::from(98));\n        assert_eq!(OpCode::dadd, OpCode::from(99));\n        assert_eq!(OpCode::isub, OpCode::from(100));\n        assert_eq!(OpCode::lsub, OpCode::from(101));\n        assert_eq!(OpCode::fsub, OpCode::from(102));\n        assert_eq!(OpCode::dsub, OpCode::from(103));\n        assert_eq!(OpCode::imul, OpCode::from(104));\n        assert_eq!(OpCode::lmul, OpCode::from(105));\n        assert_eq!(OpCode::fmul, OpCode::from(106));\n        assert_eq!(OpCode::dmul, OpCode::from(107));\n        assert_eq!(OpCode::idiv, OpCode::from(108));\n        assert_eq!(OpCode::ldiv, OpCode::from(109));\n        assert_eq!(OpCode::fdiv, OpCode::from(110));\n        assert_eq!(OpCode::ddiv, OpCode::from(111));\n        assert_eq!(OpCode::irem, OpCode::from(112));\n        assert_eq!(OpCode::lrem, OpCode::from(113));\n        assert_eq!(OpCode::frem, OpCode::from(114));\n        assert_eq!(OpCode::drem, OpCode::from(115));\n        assert_eq!(OpCode::ineg, OpCode::from(116));\n        assert_eq!(OpCode::lneg, OpCode::from(117));\n        assert_eq!(OpCode::fneg, OpCode::from(118));\n        assert_eq!(OpCode::dneg, OpCode::from(119));\n        assert_eq!(OpCode::ishl, OpCode::from(120));\n        assert_eq!(OpCode::lshl, OpCode::from(121));\n        assert_eq!(OpCode::ishr, OpCode::from(122));\n        assert_eq!(OpCode::lshr, OpCode::from(123));\n        assert_eq!(OpCode::iushr, OpCode::from(124));\n        assert_eq!(OpCode::lushr, OpCode::from(125));\n        assert_eq!(OpCode::iand, OpCode::from(126));\n        assert_eq!(OpCode::land, OpCode::from(127));\n        assert_eq!(OpCode::ior, OpCode::from(128));\n        assert_eq!(OpCode::lor, OpCode::from(129));\n        assert_eq!(OpCode::ixor, OpCode::from(130));\n        assert_eq!(OpCode::lxor, OpCode::from(131));\n        assert_eq!(OpCode::iinc, OpCode::from(132));\n        assert_eq!(OpCode::i2l, OpCode::from(133));\n        assert_eq!(OpCode::i2f, OpCode::from(134));\n        assert_eq!(OpCode::i2d, OpCode::from(135));\n        assert_eq!(OpCode::l2i, OpCode::from(136));\n        assert_eq!(OpCode::l2f, OpCode::from(137));\n        assert_eq!(OpCode::l2d, OpCode::from(138));\n        assert_eq!(OpCode::f2i, OpCode::from(139));\n        assert_eq!(OpCode::f2l, OpCode::from(140));\n        assert_eq!(OpCode::f2d, OpCode::from(141));\n        assert_eq!(OpCode::d2i, OpCode::from(142));\n        assert_eq!(OpCode::d2l, OpCode::from(143));\n        assert_eq!(OpCode::d2f, OpCode::from(144));\n        assert_eq!(OpCode::i2b, OpCode::from(145));\n        assert_eq!(OpCode::i2c, OpCode::from(146));\n        assert_eq!(OpCode::i2s, OpCode::from(147));\n        assert_eq!(OpCode::lcmp, OpCode::from(148));\n        assert_eq!(OpCode::fcmpl, OpCode::from(149));\n        assert_eq!(OpCode::fcmpg, OpCode::from(150));\n        assert_eq!(OpCode::dcmpl, OpCode::from(151));\n        assert_eq!(OpCode::dcmpg, OpCode::from(152));\n        assert_eq!(OpCode::ifeq, OpCode::from(153));\n        assert_eq!(OpCode::ifne, OpCode::from(154));\n        assert_eq!(OpCode::iflt, OpCode::from(155));\n        assert_eq!(OpCode::ifge, OpCode::from(156));\n        assert_eq!(OpCode::ifgt, OpCode::from(157));\n        assert_eq!(OpCode::ifle, OpCode::from(158));\n        assert_eq!(OpCode::if_icmpeq, OpCode::from(159));\n        assert_eq!(OpCode::if_icmpne, OpCode::from(160));\n        assert_eq!(OpCode::if_icmplt, OpCode::from(161));\n        assert_eq!(OpCode::if_icmpge, OpCode::from(162));\n        assert_eq!(OpCode::if_icmpgt, OpCode::from(163));\n        assert_eq!(OpCode::if_icmple, OpCode::from(164));\n        assert_eq!(OpCode::if_acmpeq, OpCode::from(165));\n        assert_eq!(OpCode::if_acmpne, OpCode::from(166));\n        assert_eq!(OpCode::goto, OpCode::from(167));\n        assert_eq!(OpCode::jsr, OpCode::from(168));\n        assert_eq!(OpCode::ret, OpCode::from(169));\n        assert_eq!(OpCode::tableswitch, OpCode::from(170));\n        assert_eq!(OpCode::lookupswitch, OpCode::from(171));\n        assert_eq!(OpCode::ireturn, OpCode::from(172));\n        assert_eq!(OpCode::lreturn, OpCode::from(173));\n        assert_eq!(OpCode::freturn, OpCode::from(174));\n        assert_eq!(OpCode::dreturn, OpCode::from(175));\n        assert_eq!(OpCode::areturn, OpCode::from(176));\n        assert_eq!(OpCode::return_void, OpCode::from(177));\n        assert_eq!(OpCode::getstatic, OpCode::from(178));\n        assert_eq!(OpCode::putstatic, OpCode::from(179));\n        assert_eq!(OpCode::getfield, OpCode::from(180));\n        assert_eq!(OpCode::putfield, OpCode::from(181));\n        assert_eq!(OpCode::invokevirtual, OpCode::from(182));\n        assert_eq!(OpCode::invokespecial, OpCode::from(183));\n        assert_eq!(OpCode::invokestatic, OpCode::from(184));\n        assert_eq!(OpCode::invokeinterface, OpCode::from(185));\n        assert_eq!(OpCode::invokedynamic, OpCode::from(186));\n        assert_eq!(OpCode::new, OpCode::from(187));\n        assert_eq!(OpCode::newarray, OpCode::from(188));\n        assert_eq!(OpCode::anewarray, OpCode::from(189));\n        assert_eq!(OpCode::arraylength, OpCode::from(190));\n        assert_eq!(OpCode::athrow, OpCode::from(191));\n        assert_eq!(OpCode::checkcast, OpCode::from(192));\n        assert_eq!(OpCode::instanceof, OpCode::from(193));\n        assert_eq!(OpCode::monitorenter, OpCode::from(194));\n        assert_eq!(OpCode::monitorexit, OpCode::from(195));\n        assert_eq!(OpCode::wide, OpCode::from(196));\n        assert_eq!(OpCode::multianewarray, OpCode::from(197));\n        assert_eq!(OpCode::ifnull, OpCode::from(198));\n        assert_eq!(OpCode::ifnonnull, OpCode::from(199));\n        assert_eq!(OpCode::goto_w, OpCode::from(200));\n        assert_eq!(OpCode::jsr_w, OpCode::from(201));\n        assert_eq!(OpCode::breakpoint, OpCode::from(202));\n        //        assert_eq!(OpCode::, OpCode::from(203));\n        //        assert_eq!(OpCode::, OpCode::from(204));\n        //        assert_eq!(OpCode::, OpCode::from(205));\n        //        assert_eq!(OpCode::, OpCode::from(206));\n        //        assert_eq!(OpCode::, OpCode::from(207));\n        //        assert_eq!(OpCode::, OpCode::from(208));\n        //        assert_eq!(OpCode::, OpCode::from(209));\n        //        assert_eq!(OpCode::, OpCode::from(210));\n        //        assert_eq!(OpCode::, OpCode::from(211));\n        //        assert_eq!(OpCode::, OpCode::from(212));\n        //        assert_eq!(OpCode::, OpCode::from(213));\n        //        assert_eq!(OpCode::, OpCode::from(214));\n        //        assert_eq!(OpCode::, OpCode::from(215));\n        //        assert_eq!(OpCode::, OpCode::from(216));\n        //        assert_eq!(OpCode::, OpCode::from(217));\n        //        assert_eq!(OpCode::, OpCode::from(218));\n        //        assert_eq!(OpCode::, OpCode::from(219));\n        //        assert_eq!(OpCode::, OpCode::from(220));\n        //        assert_eq!(OpCode::, OpCode::from(221));\n        //        assert_eq!(OpCode::, OpCode::from(222));\n        //        assert_eq!(OpCode::, OpCode::from(223));\n        //        assert_eq!(OpCode::, OpCode::from(224));\n        //        assert_eq!(OpCode::, OpCode::from(225));\n        //        assert_eq!(OpCode::, OpCode::from(226));\n        //        assert_eq!(OpCode::, OpCode::from(227));\n        //        assert_eq!(OpCode::, OpCode::from(228));\n        //        assert_eq!(OpCode::, OpCode::from(229));\n        //        assert_eq!(OpCode::, OpCode::from(230));\n        //        assert_eq!(OpCode::, OpCode::from(231));\n        //        assert_eq!(OpCode::, OpCode::from(232));\n        //        assert_eq!(OpCode::, OpCode::from(233));\n        //        assert_eq!(OpCode::, OpCode::from(234));\n        //        assert_eq!(OpCode::, OpCode::from(235));\n        //        assert_eq!(OpCode::, OpCode::from(236));\n        //        assert_eq!(OpCode::, OpCode::from(237));\n        //        assert_eq!(OpCode::, OpCode::from(238));\n        //        assert_eq!(OpCode::, OpCode::from(239));\n        //        assert_eq!(OpCode::, OpCode::from(240));\n        //        assert_eq!(OpCode::, OpCode::from(241));\n        //        assert_eq!(OpCode::, OpCode::from(242));\n        //        assert_eq!(OpCode::, OpCode::from(243));\n        //        assert_eq!(OpCode::, OpCode::from(244));\n        //        assert_eq!(OpCode::, OpCode::from(245));\n        //        assert_eq!(OpCode::, OpCode::from(246));\n        //        assert_eq!(OpCode::, OpCode::from(247));\n        //        assert_eq!(OpCode::, OpCode::from(248));\n        //        assert_eq!(OpCode::, OpCode::from(249));\n        //        assert_eq!(OpCode::, OpCode::from(250));\n        //        assert_eq!(OpCode::, OpCode::from(251));\n        //        assert_eq!(OpCode::, OpCode::from(252));\n        //        assert_eq!(OpCode::, OpCode::from(253));\n        assert_eq!(OpCode::impdep1, OpCode::from(254));\n        assert_eq!(OpCode::impdep2, OpCode::from(255));\n        //        assert_eq!(OpCode::, OpCode::from(256));\n    }\n}\n"
  },
  {
    "path": "crates/classfile/src/signature.rs",
    "content": "use crate::BytesRef;\nuse std::fmt::Formatter;\n\n#[derive(Clone, PartialEq)]\npub enum Type {\n    Byte,\n    Char,\n    Double,\n    Float,\n    Int,\n    Long,\n    //the 1st, container class\n    //the 2nd, generic class's arg\n    //the 3rd, if there is a '+'\n    //  Ljava/util/List<Lcom/google/inject/Module;>;)\n    //    => java.util.List<com.google.inject.Module>\n    //  Ljava/lang/Class<+Lcom/google/inject/Module;>;\n    //    => java.lang.Class<? extends com.google.inject.Module>\n    Object(BytesRef, Option<Vec<Type>>, Option<u8>),\n    Short,\n    Boolean,\n    Array(BytesRef),\n    Void,\n}\n\nimpl std::fmt::Debug for Type {\n    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {\n        match self {\n            Type::Byte => write!(f, \"B\"),\n            Type::Char => write!(f, \"C\"),\n            Type::Double => write!(f, \"D\"),\n            Type::Float => write!(f, \"F\"),\n            Type::Int => write!(f, \"I\"),\n            Type::Long => write!(f, \"J\"),\n            Type::Object(container, args, prefix) => {\n                write!(f, \"Object(\");\n                write!(f, \"\\\"{}\\\",\", String::from_utf8_lossy(container.as_slice()));\n                write!(f, \"{:?},\", args);\n                write!(f, \"{:?}\", prefix);\n                write!(f, \")\")\n            }\n            Type::Short => write!(f, \"S\"),\n            Type::Boolean => write!(f, \"Z\"),\n            Type::Array(desc) => write!(f, \"Array({})\", String::from_utf8_lossy(desc.as_slice())),\n            Type::Void => write!(f, \"V\"),\n        }\n    }\n}\n"
  },
  {
    "path": "crates/classfile/src/version.rs",
    "content": "use crate::U2;\n\n#[derive(Debug)]\npub struct Version {\n    pub minor: U2,\n    pub major: U2,\n}\n"
  },
  {
    "path": "crates/vm/Cargo.toml",
    "content": "[package]\nname = \"vm\"\nversion = \"0.1.0\"\nauthors = [\"Dou Chuan <1843657913@qq.com>\"]\nedition = \"2018\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\nchrono = \"0.4\"\nclassfile = { path = \"../classfile\", version = \"0.1.0\" }\nclass-parser = { path=\"../class-parser\", version=\"0.1.0\" }\ndirs = \"3.0.1\"\nlazy_static = \"1.4.0\"\nlibc = \"0.2.85\"\nlog = \"0.4\"\nnix = \"0.19.1\"\nrustc-hash = \"1.1.0\"\nzip = \"0.5.9\"\n"
  },
  {
    "path": "crates/vm/README.md",
    "content": "## Java Virtual Machine\nThis is the `vm` crate, which contains implementation of Java Virtual Machine.\nThe implementation based on `Java SE 8 Edition`."
  },
  {
    "path": "crates/vm/src/lib.rs",
    "content": "#[macro_use]\nextern crate lazy_static;\n#[macro_use]\nextern crate log;\n\n//contains macros, must be here\n#[macro_use]\npub mod util;\n\npub mod native;\npub mod oop;\npub mod runtime;\npub mod types;\n\npub fn init_vm() {\n    oop::init();\n    runtime::init();\n    native::init();\n}\n\n#[inline]\npub fn new_br(s: &str) -> classfile::BytesRef {\n    std::sync::Arc::new(Vec::from(s))\n}\n"
  },
  {
    "path": "crates/vm/src/native/common/check_format.rs",
    "content": "// pub fn is_valid_class_name(s: &String) -> bool {\n//     if s.contains(\"/\") {\n//         return false;\n//     }\n//\n//     true\n// }\n"
  },
  {
    "path": "crates/vm/src/native/common/mod.rs",
    "content": "mod check_format;\npub mod reflect;\n"
  },
  {
    "path": "crates/vm/src/native/common/reflect.rs",
    "content": "#![allow(non_snake_case)]\n\nuse crate::native::java_lang_Class;\nuse crate::oop::{self, Class, Oop, OopPtr};\nuse crate::runtime::{self, require_class3};\nuse crate::types::*;\nuse crate::util;\nuse class_parser::{FieldSignature, MethodSignature};\nuse classfile::consts as cls_const;\nuse classfile::SignatureType;\nuse std::sync::Arc;\n\npub fn new_field(fir: FieldIdRef) -> Oop {\n    let field_cls = runtime::require_class3(None, cls_const::J_FIELD).unwrap();\n\n    let clazz = fir.field.class.get_class().get_mirror();\n\n    let field_sig = FieldSignature::new(fir.field.desc.as_slice());\n    let typ_mirror = create_value_type(field_sig.field_type);\n    let desc = unsafe { std::str::from_utf8_unchecked(fir.field.desc.as_slice()) };\n    let signature = util::oop::new_java_lang_string2(desc);\n\n    let field_name = unsafe { std::str::from_utf8_unchecked(fir.field.name.as_slice()) };\n    let mut desc = Vec::new();\n    desc.push(b'(');\n    let mut args: Vec<Oop> = vec![\n        (\"clazz\", \"Ljava/lang/Class;\", clazz),\n        (\n            \"name\",\n            \"Ljava/lang/String;\",\n            util::oop::new_java_lang_string2(field_name),\n        ),\n        (\"type\", \"Ljava/lang/Class;\", typ_mirror),\n        (\"modifiers\", \"I\", Oop::new_int(fir.field.acc_flags as i32)),\n        (\"slot\", \"I\", Oop::new_int(fir.offset as i32)),\n        (\"signature\", \"Ljava/lang/String;\", signature),\n        (\"annotations\", \"[B\", Oop::Null),\n    ]\n    .iter()\n    .map(|(_, t, v)| {\n        desc.extend_from_slice(t.as_bytes());\n        v.clone()\n    })\n    .collect();\n    desc.extend_from_slice(b\")V\");\n\n    let oop = Oop::new_inst(field_cls.clone());\n    args.insert(0, oop.clone());\n    runtime::invoke::invoke_ctor(field_cls, Arc::new(desc), args);\n\n    oop\n}\n\npub fn new_method_ctor(mir: MethodIdRef) -> Oop {\n    let ctor_cls = require_class3(None, cls_const::J_METHOD_CTOR).unwrap();\n\n    //declaringClass\n    let declaring_cls = mir.method.class.get_class().get_mirror();\n\n    //parameterTypes\n    let signature = MethodSignature::new(mir.method.desc.as_slice());\n    let params: Vec<Oop> = signature\n        .args\n        .iter()\n        .map(|t| create_value_type(t.clone()))\n        .collect();\n    let cls = require_class3(None, b\"[Ljava/lang/Class;\").unwrap();\n    let parameter_types = Oop::new_ref_ary2(cls, params);\n\n    //fixme: checkedExceptions\n    let cls = require_class3(None, b\"[Ljava/lang/Class;\").unwrap();\n    let checked_exceptions = Oop::new_ref_ary2(cls, vec![]);\n\n    //modifiers\n    let modifiers = mir.method.acc_flags;\n    //slot\n    let slot = mir.offset;\n    //signature\n    let desc = unsafe { std::str::from_utf8_unchecked(mir.method.desc.as_slice()) };\n    let signature = util::oop::new_java_lang_string2(desc);\n    let annotations = {\n        let raw = mir.method.get_annotation();\n        match raw {\n            Some(raw) => Oop::new_byte_ary2(raw.to_vec()),\n            None => Oop::Null,\n        }\n    };\n    let parameter_annotations = {\n        let raw = mir.method.get_param_annotation();\n        match raw {\n            Some(raw) => Oop::new_byte_ary2(raw.to_vec()),\n            None => Oop::Null,\n        }\n    };\n\n    let mut desc = Vec::new();\n    desc.push(b'(');\n    let mut args: Vec<Oop> = vec![\n        (\"declaringClass\", \"Ljava/lang/Class;\", declaring_cls),\n        (\"parameterTypes\", \"[Ljava/lang/Class;\", parameter_types),\n        (\n            \"checkedExceptions\",\n            \"[Ljava/lang/Class;\",\n            checked_exceptions,\n        ),\n        (\"modifiers\", \"I\", Oop::new_int(modifiers as i32)),\n        (\"slot\", \"I\", Oop::new_int(slot as i32)),\n        (\"signature\", \"Ljava/lang/String;\", signature),\n        (\"annotations\", \"[B\", annotations),\n        (\"parameterAnnotations\", \"[B\", parameter_annotations),\n    ]\n    .iter()\n    .map(|(_, t, v)| {\n        desc.extend_from_slice(t.as_bytes());\n        v.clone()\n    })\n    .collect();\n    desc.extend_from_slice(b\")V\");\n\n    let oop = Oop::new_inst(ctor_cls.clone());\n    args.insert(0, oop.clone());\n    runtime::invoke::invoke_ctor(ctor_cls, Arc::new(desc), args);\n\n    oop\n}\n\npub fn new_method_normal(mir: MethodIdRef) -> Oop {\n    let ctor_cls = require_class3(None, cls_const::J_METHOD).unwrap();\n\n    //declaringClass\n    let declaring_cls = mir.method.class.get_class().get_mirror();\n\n    //name\n    let name = {\n        let name = unsafe { std::str::from_utf8_unchecked(mir.method.name.as_slice()) };\n        util::oop::new_java_lang_string2(name)\n    };\n\n    //parameterTypes\n    let signature = MethodSignature::new(mir.method.desc.as_slice());\n    let params: Vec<Oop> = signature\n        .args\n        .iter()\n        .map(|t| create_value_type(t.clone()))\n        .collect();\n    let cls = require_class3(None, b\"[Ljava/lang/Class;\").unwrap();\n    let parameter_types = Oop::new_ref_ary2(cls, params);\n\n    //returnType\n    let return_type = create_value_type(signature.retype);\n\n    //fixme: checkedExceptions\n    let cls = require_class3(None, b\"[Ljava/lang/Class;\").unwrap();\n    let checked_exceptions = Oop::new_ref_ary2(cls, vec![]);\n\n    //modifiers\n    let modifiers = mir.method.acc_flags;\n    //slot\n    let slot = mir.offset;\n    //signature\n    let signature = {\n        let desc = unsafe { std::str::from_utf8_unchecked(mir.method.desc.as_slice()) };\n        util::oop::new_java_lang_string2(desc)\n    };\n    let annotations = {\n        let raw = mir.method.get_annotation();\n        match raw {\n            Some(raw) => Oop::new_byte_ary2(raw.to_vec()),\n            None => Oop::Null,\n        }\n    };\n    let parameter_annotations = {\n        let raw = mir.method.get_param_annotation();\n        match raw {\n            Some(raw) => Oop::new_byte_ary2(raw.to_vec()),\n            None => Oop::Null,\n        }\n    };\n    let annotation_default = {\n        let raw = mir.method.get_annotation_default();\n        match raw {\n            Some(raw) => Oop::new_byte_ary2(raw.to_vec()),\n            None => Oop::Null,\n        }\n    };\n\n    let mut desc = Vec::new();\n    desc.push(b'(');\n    let mut args: Vec<Oop> = vec![\n        (\"declaringClass\", \"Ljava/lang/Class;\", declaring_cls),\n        (\"name\", \"Ljava/lang/String;\", name),\n        (\"parameterTypes\", \"[Ljava/lang/Class;\", parameter_types),\n        (\"returnType\", \"Ljava/lang/Class;\", return_type),\n        (\n            \"checkedExceptions\",\n            \"[Ljava/lang/Class;\",\n            checked_exceptions,\n        ),\n        (\"modifiers\", \"I\", Oop::new_int(modifiers as i32)),\n        (\"slot\", \"I\", Oop::new_int(slot as i32)),\n        (\"signature\", \"Ljava/lang/String;\", signature),\n        (\"annotations\", \"[B\", annotations),\n        (\"parameterAnnotations\", \"[B\", parameter_annotations),\n        (\"annotationDefault\", \"[B\", annotation_default),\n    ]\n    .iter()\n    .map(|(_, t, v)| {\n        desc.extend_from_slice(t.as_bytes());\n        v.clone()\n    })\n    .collect();\n    desc.extend_from_slice(b\")V\");\n\n    let oop = Oop::new_inst(ctor_cls.clone());\n    args.insert(0, oop.clone());\n    runtime::invoke::invoke_ctor(ctor_cls, Arc::new(desc), args);\n\n    oop\n}\n\npub fn get_Constructor_clazz(ctor: &Oop) -> Oop {\n    //todo: optimize, avoid obtain class\n    let cls = {\n        let rf = ctor.extract_ref();\n        let inst = rf.extract_inst();\n        inst.class.clone()\n    };\n\n    //todo: optimize, avoid obtain id\n    let cls = cls.get_class();\n    let id = cls.get_field_id(&util::S_CLAZZ, &util::S_JAVA_LANG_CLASS, false);\n    Class::get_field_value(ctor.extract_ref(), id)\n}\n\n/*\npub fn get_Constructor_slot(ctor: &Oop) -> i32 {\n    let cls = {\n        let v = util::oop::extract_ref(ctor);\n        let v = v.read().unwrap();\n        match &v.v {\n            oop::RefKind::Inst(inst) => inst.class.clone(),\n            _ => unreachable!(),\n        }\n    };\n\n    let cls = cls.read().unwrap();\n    let id = cls.get_field_id(b\"slot\", b\"I\", false);\n    let v = cls.get_field_value(ctor, id);\n    util::oop::extract_int(&v)\n}\n*/\n\npub fn get_Constructor_signature(ctor: &Oop) -> String {\n    //todo: optimisze, cache Constructor cls, avoid obtain class\n    let cls = {\n        let rf = ctor.extract_ref();\n        let inst = rf.extract_inst();\n        inst.class.clone()\n    };\n\n    //todo: optimize, cache id\n    let cls = cls.get_class();\n    let id = cls.get_field_id(&util::S_SIGNATURE, &util::S_JAVA_LANG_STRING, false);\n    let v = Class::get_field_value(ctor.extract_ref(), id);\n    OopPtr::java_lang_string(v.extract_ref())\n}\n\nfn create_value_type(t: SignatureType) -> Oop {\n    match t {\n        SignatureType::Byte => java_lang_Class::get_primitive_class_mirror(\"B\").unwrap(),\n        SignatureType::Char => java_lang_Class::get_primitive_class_mirror(\"C\").unwrap(),\n        SignatureType::Int => java_lang_Class::get_primitive_class_mirror(\"I\").unwrap(),\n        SignatureType::Double => java_lang_Class::get_primitive_class_mirror(\"D\").unwrap(),\n        SignatureType::Float => java_lang_Class::get_primitive_class_mirror(\"F\").unwrap(),\n        SignatureType::Long => java_lang_Class::get_primitive_class_mirror(\"J\").unwrap(),\n        SignatureType::Object(desc, _, _) => {\n            let len = desc.len();\n            let name = &desc.as_slice()[1..len - 1];\n            let cls = require_class3(None, name).unwrap();\n            let cls = cls.get_class();\n            cls.get_mirror()\n        }\n        SignatureType::Short => java_lang_Class::get_primitive_class_mirror(\"S\").unwrap(),\n        SignatureType::Boolean => java_lang_Class::get_primitive_class_mirror(\"Z\").unwrap(),\n        SignatureType::Array(desc) => {\n            let cls = require_class3(None, desc.as_slice()).unwrap();\n            let cls = cls.get_class();\n            cls.get_mirror()\n        }\n        SignatureType::Void => java_lang_Class::get_primitive_class_mirror(\"V\").unwrap(),\n    }\n}\n"
  },
  {
    "path": "crates/vm/src/native/java_io_FileDescriptor.rs",
    "content": "#![allow(non_snake_case)]\n\nuse crate::native::{new_fn, JNIEnv, JNINativeMethod, JNIResult};\nuse crate::oop::Oop;\n\npub fn get_native_methods() -> Vec<JNINativeMethod> {\n    vec![new_fn(\"initIDs\", \"()V\", Box::new(jvm_initIDs))]\n}\n\nfn jvm_initIDs(_env: JNIEnv, _args: &[Oop]) -> JNIResult {\n    Ok(None)\n}\n"
  },
  {
    "path": "crates/vm/src/native/java_io_FileInputStream.rs",
    "content": "#![allow(non_snake_case)]\nuse crate::native::{new_fn, JNIEnv, JNINativeMethod, JNIResult};\nuse crate::oop::{Class, Oop, OopPtr};\nuse crate::runtime::{self, require_class3};\nuse crate::util;\nuse classfile::consts as cls_consts;\n\nstatic mut FILE_INPUT_STREAM_FD: usize = 0;\nstatic mut FILE_DESCRIPTOR_FD: usize = 0;\n\npub fn get_native_methods() -> Vec<JNINativeMethod> {\n    vec![\n        new_fn(\"initIDs\", \"()V\", Box::new(jvm_initIDs)),\n        new_fn(\"open0\", \"(Ljava/lang/String;)V\", Box::new(jvm_open0)),\n        new_fn(\"readBytes\", \"([BII)I\", Box::new(jvm_readBytes)),\n        //available0 used by zulu8 jdk\n        new_fn(\"available0\", \"()I\", Box::new(jvm_available0)),\n        new_fn(\"available\", \"()I\", Box::new(jvm_available0)),\n        new_fn(\"close0\", \"()V\", Box::new(jvm_close0)),\n    ]\n}\n\nfn jvm_initIDs(_env: JNIEnv, _args: &[Oop]) -> JNIResult {\n    //setup: java.io.FileInputStream fd\n    let cls = require_class3(None, b\"java/io/FileInputStream\").unwrap();\n    let cls = cls.get_class();\n    let id = cls.get_field_id(&util::S_FD, &util::S_JAVA_IO_FD, false);\n    unsafe {\n        FILE_INPUT_STREAM_FD = id.offset;\n    }\n\n    //setup: java.io.FileDescriptor fd\n    let cls = require_class3(None, b\"java/io/FileDescriptor\").unwrap();\n    let cls = cls.get_class();\n    let id = cls.get_field_id(&util::S_FD, &util::S_I, false);\n    unsafe {\n        FILE_DESCRIPTOR_FD = id.offset;\n    }\n\n    Ok(None)\n}\n\nfn jvm_open0(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let this = args.get(0).unwrap();\n    let name = {\n        let v = args.get(1).unwrap();\n        OopPtr::java_lang_string(v.extract_ref())\n    };\n    let fd = unsafe {\n        use std::ffi::CString;\n        let name = CString::new(name).unwrap();\n        libc::open(name.as_ptr(), libc::O_RDONLY)\n    };\n\n    set_file_descriptor_fd(this, fd);\n\n    Ok(None)\n}\n\nfn jvm_readBytes(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let this = args.get(0).unwrap();\n    let fd = get_file_descriptor_fd(this);\n    let byte_ary = args.get(1).unwrap();\n    let off = args.get(2).unwrap().extract_int();\n    let len = args.get(3).unwrap().extract_int();\n\n    let n = {\n        let rf = byte_ary.extract_ref();\n        let ary = rf.extract_mut_type_array();\n        let ary = ary.extract_mut_bytes();\n\n        let (_, ptr) = ary.split_at_mut(off as usize);\n        let ptr = ptr.as_mut_ptr() as *mut libc::c_void;\n        let n = unsafe { libc::read(fd, ptr, len as usize) };\n        // error!(\"readBytes n = {}\", n);\n        if n > 0 {\n            n as i32\n        } else if n == -1 {\n            let ex = runtime::exception::new(\n                cls_consts::J_IOEXCEPTION,\n                Some(String::from(\"Read Error\")),\n            );\n            error!(\"jvm_readBytes read error\");\n            return Err(ex);\n        } else {\n            -1\n        }\n    };\n\n    Ok(Some(Oop::new_int(n)))\n}\n\nfn jvm_available0(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let this = args.get(0).unwrap();\n    let fd = get_file_descriptor_fd(this);\n\n    if fd == -1 {\n        unimplemented!(\"Stream Closed\");\n    }\n\n    let mut size = -1i64;\n\n    unsafe {\n        let mut stat: libc::stat = std::mem::zeroed();\n        if libc::fstat(fd, &mut stat) != -1 {\n            let mode = stat.st_mode;\n            if (mode & libc::S_IFIFO == libc::S_IFIFO)\n                || (mode & libc::S_IFCHR == libc::S_IFCHR)\n                || (mode & libc::S_IFSOCK == libc::S_IFSOCK)\n            {\n                let mut n = 0;\n                if libc::ioctl(fd, libc::FIONREAD, &mut n) >= 0 {\n                    return Ok(Some(Oop::new_int(n)));\n                }\n            } else if mode & libc::S_IFREG == libc::S_IFREG {\n                size = stat.st_size;\n            }\n        }\n\n        let current = libc::lseek(fd, 0, libc::SEEK_CUR);\n        if current == -1 {\n            return Ok(Some(Oop::new_int(0)));\n        }\n\n        if size < current {\n            size = libc::lseek(fd, 0, libc::SEEK_END);\n            if size == -1 {\n                return Ok(Some(Oop::new_int(0)));\n            }\n\n            if libc::lseek(fd, current, libc::SEEK_SET) == -1 {\n                return Ok(Some(Oop::new_int(0)));\n            }\n        }\n\n        Ok(Some(Oop::new_int((size - current) as i32)))\n    }\n}\n\nfn jvm_close0(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let this = args.get(0).unwrap();\n    let fd = get_file_descriptor_fd(this);\n    unsafe {\n        libc::close(fd);\n    }\n    Ok(None)\n}\n\nfn set_file_descriptor_fd(fin: &Oop, fd: i32) {\n    let offset = unsafe { FILE_INPUT_STREAM_FD };\n    let fd_this = Class::get_field_value2(fin.extract_ref(), offset);\n\n    let offset = unsafe { FILE_DESCRIPTOR_FD };\n    Class::put_field_value2(fd_this.extract_ref(), offset, Oop::new_int(fd));\n}\n\nfn get_file_descriptor_fd(fin: &Oop) -> i32 {\n    let offset = unsafe { FILE_INPUT_STREAM_FD };\n    let fd_this = Class::get_field_value2(fin.extract_ref(), offset);\n\n    let offset = unsafe { FILE_DESCRIPTOR_FD };\n    let fd = Class::get_field_value2(fd_this.extract_ref(), offset);\n    fd.extract_int()\n}\n"
  },
  {
    "path": "crates/vm/src/native/java_io_FileOutputStream.rs",
    "content": "#![allow(non_snake_case)]\n\nuse crate::native::{new_fn, JNIEnv, JNINativeMethod, JNIResult};\nuse crate::oop::{Class, Oop, OopPtr};\nuse crate::runtime::require_class3;\nuse crate::util;\n\nstatic mut FILE_OUTPUT_STREAM_FD: usize = 0;\nstatic mut FILE_DESCRIPTOR_FD: usize = 0;\n\npub fn get_native_methods() -> Vec<JNINativeMethod> {\n    vec![\n        new_fn(\"initIDs\", \"()V\", Box::new(jvm_initIDs)),\n        new_fn(\"writeBytes\", \"([BIIZ)V\", Box::new(jvm_writeBytes)),\n        new_fn(\"open0\", \"(Ljava/lang/String;Z)V\", Box::new(jvm_open0)),\n    ]\n}\n\nfn jvm_initIDs(_env: JNIEnv, _args: &[Oop]) -> JNIResult {\n    //setup: java.io.FileOutputStream fd\n    let cls = require_class3(None, b\"java/io/FileOutputStream\").unwrap();\n    let cls = cls.get_class();\n    let id = cls.get_field_id(&util::S_FD, &util::S_JAVA_IO_FD, false);\n    unsafe {\n        FILE_OUTPUT_STREAM_FD = id.offset;\n    }\n\n    //setup: java.io.FileDescriptor fd\n    let cls = require_class3(None, b\"java/io/FileDescriptor\").unwrap();\n    let cls = cls.get_class();\n    let id = cls.get_field_id(&util::S_FD, &util::S_I, false);\n    unsafe {\n        FILE_DESCRIPTOR_FD = id.offset;\n    }\n\n    Ok(None)\n}\n\nfn jvm_writeBytes(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let os = args.get(0).unwrap();\n    let fd = get_file_descriptor_fd(os);\n    let byte_ary = args.get(1).unwrap();\n    let off = args.get(2).unwrap().extract_int();\n    let len = args.get(3).unwrap().extract_int();\n    let append = args.get(4).unwrap().extract_int();\n\n    let rf = byte_ary.extract_ref();\n    let ary = rf.extract_type_array();\n    let ary = ary.extract_bytes();\n    let (_, ary) = ary.split_at(off as usize);\n    let len = len as usize;\n\n    unsafe {\n        if append == 1 {\n            libc::lseek(fd, 0, libc::SEEK_END);\n        }\n\n        if -1 == libc::write(fd, ary.as_ptr() as *const libc::c_void, len) {\n            panic!(\"write failed\");\n        }\n    }\n\n    Ok(None)\n}\n\nfn jvm_open0(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let this = args.get(0).unwrap();\n    let name = args.get(1).unwrap();\n    let name = OopPtr::java_lang_string(name.extract_ref());\n    let append = {\n        let v = args.get(2).unwrap().extract_int();\n        v == 1\n    };\n    let fd = unsafe {\n        use std::ffi::CString;\n        let name = CString::new(name).unwrap();\n        let mut flag = libc::O_WRONLY | libc::O_CREAT;\n        if append {\n            flag |= libc::O_APPEND;\n        } else {\n            flag |= libc::O_TRUNC;\n        }\n        libc::open(name.as_ptr(), flag)\n    };\n\n    set_file_descriptor_fd(this, fd);\n\n    Ok(None)\n}\n\nfn get_file_descriptor_fd(fos: &Oop) -> i32 {\n    let fd_this = {\n        let offset = unsafe { FILE_OUTPUT_STREAM_FD };\n        Class::get_field_value2(fos.extract_ref(), offset)\n    };\n\n    let fd = {\n        let offset = unsafe { FILE_DESCRIPTOR_FD };\n        Class::get_field_value2(fd_this.extract_ref(), offset)\n    };\n\n    fd.extract_int()\n}\n\nfn set_file_descriptor_fd(fos: &Oop, fd: i32) {\n    let fd_this = {\n        let offset = unsafe { FILE_OUTPUT_STREAM_FD };\n        Class::get_field_value2(fos.extract_ref(), offset)\n    };\n\n    let offset = unsafe { FILE_DESCRIPTOR_FD };\n    Class::put_field_value2(fd_this.extract_ref(), offset, Oop::new_int(fd));\n}\n"
  },
  {
    "path": "crates/vm/src/native/java_io_UnixFileSystem.rs",
    "content": "#![allow(non_snake_case)]\n\nuse crate::native::{new_fn, JNIEnv, JNINativeMethod, JNIResult};\nuse crate::oop::{Class, Oop, OopPtr};\nuse crate::runtime::require_class3;\nuse crate::{new_br, util};\nuse std::fs;\n\nstatic mut FILE_PATH: usize = 0;\n\n//FileSystem.java define\nconst BA_EXISTS: i32 = 0x01;\nconst BA_REGULAR: i32 = 0x02;\nconst BA_DIRECTORY: i32 = 0x04;\nconst _BA_HIDDEN: i32 = 0x08;\nconst ACCESS_READ: i32 = 0x04;\nconst ACCESS_WRITE: i32 = 0x02;\nconst ACCESS_EXECUTE: i32 = 0x01;\n\npub fn get_native_methods() -> Vec<JNINativeMethod> {\n    vec![\n        new_fn(\"initIDs\", \"()V\", Box::new(jvm_initIDs)),\n        new_fn(\n            \"getBooleanAttributes0\",\n            \"(Ljava/io/File;)I\",\n            Box::new(jvm_getBooleanAttributes0),\n        ),\n        new_fn(\n            \"checkAccess\",\n            \"(Ljava/io/File;I)Z\",\n            Box::new(jvm_checkAccess),\n        ),\n        new_fn(\n            \"canonicalize0\",\n            \"(Ljava/lang/String;)Ljava/lang/String;\",\n            Box::new(jvm_canonicalize0),\n        ),\n        new_fn(\n            \"createFileExclusively\",\n            \"(Ljava/lang/String;)Z\",\n            Box::new(jvm_createFileExclusively),\n        ),\n    ]\n}\n\nfn jvm_initIDs(_env: JNIEnv, _args: &[Oop]) -> JNIResult {\n    let cls = require_class3(None, b\"java/io/File\").unwrap();\n    let cls = cls.get_class();\n    let fir = cls.get_field_id(&new_br(\"path\"), &util::S_JAVA_LANG_STRING, false);\n    unsafe {\n        FILE_PATH = fir.offset;\n    }\n\n    Ok(None)\n}\n\nfn jvm_getBooleanAttributes0(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let file = args.get(1).unwrap();\n    let path = get_File_path(file);\n\n    let mut r = 0;\n    if let Ok(attr) = fs::metadata(path) {\n        r |= BA_EXISTS;\n        if attr.is_file() {\n            r |= BA_REGULAR;\n        }\n        if attr.is_dir() {\n            r |= BA_DIRECTORY;\n        }\n    }\n\n    Ok(Some(Oop::new_int(r)))\n}\n\nfn jvm_checkAccess(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let file = args.get(1).unwrap();\n    let path = get_File_path(file);\n\n    let access = args.get(2).unwrap().extract_int();\n\n    let mut amode = 0;\n    if (access & ACCESS_READ) == ACCESS_READ {\n        amode |= libc::R_OK;\n    }\n    if (access & ACCESS_WRITE) == ACCESS_WRITE {\n        amode |= libc::W_OK;\n    }\n    if (access & ACCESS_EXECUTE) == ACCESS_EXECUTE {\n        amode |= libc::X_OK;\n    }\n\n    let r = unsafe {\n        use std::ffi::CString;\n        let path = CString::new(path).unwrap();\n        if libc::access(path.as_ptr(), amode) == 0 {\n            1\n        } else {\n            0\n        }\n    };\n\n    Ok(Some(Oop::new_int(r)))\n}\n\nfn jvm_canonicalize0(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let path = args.get(1).unwrap();\n    let path = OopPtr::java_lang_string(path.extract_ref());\n    let path = std::path::Path::new(&path);\n    let path = path.canonicalize().expect(\"path canonicalize failed\");\n    let path = path.to_str().expect(\"path to_str failed\");\n    let path = util::oop::new_java_lang_string2(path);\n\n    Ok(Some(path))\n}\n\nfn jvm_createFileExclusively(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let path = args.get(1).unwrap();\n    let path = OopPtr::java_lang_string(path.extract_ref());\n    let v = match std::fs::OpenOptions::new()\n        .read(true)\n        .write(true)\n        .create(true)\n        .open(&path)\n    {\n        Ok(_) => 1,\n        Err(e) => {\n            error!(\"open {}, error = {:?}\", path, e);\n            0\n        }\n    };\n    Ok(Some(Oop::new_int(v)))\n}\n\nfn get_File_path(file: &Oop) -> String {\n    let offset = unsafe { FILE_PATH };\n    let path = Class::get_field_value2(file.extract_ref(), offset);\n    OopPtr::java_lang_string(path.extract_ref())\n}\n"
  },
  {
    "path": "crates/vm/src/native/java_lang_Class.rs",
    "content": "#![allow(non_snake_case)]\n\nuse crate::native::{common, new_fn, JNIEnv, JNINativeMethod, JNIResult};\nuse crate::oop::{self, Class, ClassKind, Oop, OopPtr, ValueType};\nuse crate::runtime::{self, require_class2, require_class3};\nuse crate::types::{ClassRef, MethodIdRef};\nuse crate::util;\nuse classfile::{constant_pool, consts as cls_consts, flags as acc};\nuse rustc_hash::FxHashMap;\nuse std::sync::{Arc, RwLock};\n\npub fn get_primitive_class_mirror(key: &str) -> Option<Oop> {\n    //todo: avoid mutex lock, it's only read\n    let mirrors = PRIM_MIRROS.read().unwrap();\n    mirrors.get(key).cloned()\n}\n\npub fn get_native_methods() -> Vec<JNINativeMethod> {\n    vec![\n        new_fn(\"registerNatives\", \"()V\", Box::new(jvm_registerNatives)),\n        new_fn(\n            \"desiredAssertionStatus0\",\n            \"(Ljava/lang/Class;)Z\",\n            Box::new(jvm_desiredAssertionStatus0),\n        ),\n        new_fn(\n            \"getPrimitiveClass\",\n            \"(Ljava/lang/String;)Ljava/lang/Class;\",\n            Box::new(jvm_getPrimitiveClass),\n        ),\n        new_fn(\n            \"getDeclaredFields0\",\n            \"(Z)[Ljava/lang/reflect/Field;\",\n            Box::new(jvm_getDeclaredFields0),\n        ),\n        new_fn(\"getName0\", \"()Ljava/lang/String;\", Box::new(jvm_getName0)),\n        new_fn(\n            \"forName0\",\n            \"(Ljava/lang/String;ZLjava/lang/ClassLoader;Ljava/lang/Class;)Ljava/lang/Class;\",\n            Box::new(jvm_forName0),\n        ),\n        new_fn(\"isPrimitive\", \"()Z\", Box::new(jvm_isPrimitive)),\n        new_fn(\n            \"isAssignableFrom\",\n            \"(Ljava/lang/Class;)Z\",\n            Box::new(jvm_isAssignableFrom),\n        ),\n        new_fn(\"isInterface\", \"()Z\", Box::new(jvm_isInterface)),\n        new_fn(\n            \"getDeclaredConstructors0\",\n            \"(Z)[Ljava/lang/reflect/Constructor;\",\n            Box::new(jvm_getDeclaredConstructors0),\n        ),\n        new_fn(\"getModifiers\", \"()I\", Box::new(jvm_getModifiers)),\n        new_fn(\n            \"getSuperclass\",\n            \"()Ljava/lang/Class;\",\n            Box::new(jvm_getSuperclass),\n        ),\n        new_fn(\"isArray\", \"()Z\", Box::new(jvm_isArray)),\n        new_fn(\n            \"getComponentType\",\n            \"()Ljava/lang/Class;\",\n            Box::new(jvm_getComponentType),\n        ),\n        new_fn(\n            \"getEnclosingMethod0\",\n            \"()[Ljava/lang/Object;\",\n            Box::new(jvm_getEnclosingMethod0),\n        ),\n        new_fn(\n            \"getDeclaringClass0\",\n            \"()Ljava/lang/Class;\",\n            Box::new(jvm_getDeclaringClass0),\n        ),\n        new_fn(\n            \"isInstance\",\n            \"(Ljava/lang/Object;)Z\",\n            Box::new(jvm_isInstance),\n        ),\n        new_fn(\n            \"getDeclaredMethods0\",\n            \"(Z)[Ljava/lang/reflect/Method;\",\n            Box::new(jvm_getDeclaredMethods0),\n        ),\n        new_fn(\n            \"getInterfaces0\",\n            \"()[Ljava/lang/Class;\",\n            Box::new(jvm_getInterfaces0),\n        ),\n        new_fn(\"getRawAnnotations\", \"()[B\", Box::new(jvm_getRawAnnotations)),\n        new_fn(\n            \"getConstantPool\",\n            \"()Lsun/reflect/ConstantPool;\",\n            Box::new(jvm_getConstantPool),\n        ),\n        new_fn(\n            \"getDeclaredClasses0\",\n            \"()[Ljava/lang/Class;\",\n            Box::new(jvm_getDeclaredClasses0),\n        ),\n        new_fn(\n            \"getGenericSignature0\",\n            \"()Ljava/lang/String;\",\n            Box::new(jvm_getGenericSignature0),\n        ),\n    ]\n}\n\n#[derive(Copy, Clone, PartialEq)]\nenum ClassMirrorState {\n    NotFixed,\n    Fixed,\n}\n\nlazy_static! {\n    static ref MIRROR_STATE: RwLock<ClassMirrorState> = RwLock::new(ClassMirrorState::NotFixed);\n    static ref PRIM_MIRROS: RwLock<FxHashMap<String, Oop>> = {\n        let hm = FxHashMap::default();\n        RwLock::new(hm)\n    };\n    static ref SIGNATURE_DIC: FxHashMap<&'static str, &'static str> = {\n        let dic: FxHashMap<&'static str, &'static str> = [\n            (\"byte\", \"B\"),\n            (\"boolean\", \"Z\"),\n            (\"char\", \"C\"),\n            (\"short\", \"S\"),\n            (\"int\", \"I\"),\n            (\"float\", \"F\"),\n            (\"long\", \"J\"),\n            (\"double\", \"D\"),\n            (\"void\", \"V\"),\n        ]\n        .iter()\n        .cloned()\n        .collect();\n\n        dic\n    };\n    static ref DELAYED_MIRROS: RwLock<Vec<String>> = {\n        let v = vec![\n            \"I\", \"Z\", \"B\", \"C\", \"S\", \"F\", \"J\", \"D\", \"V\", \"[I\", \"[Z\", \"[B\", \"[C\", \"[S\", \"[F\", \"[J\",\n            \"[D\",\n        ];\n        let v: Vec<String> = v.iter().map(|it| it.to_string()).collect();\n        RwLock::new(v)\n    };\n    static ref DELAYED_ARY_MIRROS: RwLock<Vec<ClassRef>> = {\n        let v = vec![];\n        RwLock::new(v)\n    };\n}\n\npub fn init() {\n    lazy_static::initialize(&MIRROR_STATE);\n    lazy_static::initialize(&SIGNATURE_DIC);\n    lazy_static::initialize(&PRIM_MIRROS);\n    lazy_static::initialize(&DELAYED_MIRROS);\n    lazy_static::initialize(&DELAYED_ARY_MIRROS);\n}\n\npub fn create_mirror(cls: ClassRef) {\n    let is_fixed = {\n        let s = MIRROR_STATE.write().unwrap();\n        *s == ClassMirrorState::Fixed\n    };\n\n    if is_fixed {\n        let mirror = Oop::new_mirror(cls.clone());\n        let cls = cls.get_mut_class();\n        trace!(\"mirror created: {}\", unsafe {\n            std::str::from_utf8_unchecked(cls.name.as_slice())\n        });\n        cls.set_mirror(mirror);\n    } else {\n        let cls_back = cls.clone();\n        let cls = cls.get_class();\n        let name = unsafe { std::str::from_utf8_unchecked(cls.name.as_slice()) };\n        warn!(\"mirror create delayed: {}\", name);\n        match cls.kind {\n            oop::class::ClassKind::Instance(_) => {\n                let mut mirrors = DELAYED_MIRROS.write().unwrap();\n                mirrors.push(String::from(name));\n            }\n            _ => {\n                let mut mirrors = DELAYED_ARY_MIRROS.write().unwrap();\n                mirrors.push(cls_back);\n            }\n        }\n    }\n}\n\n/*\ncalled after 'java/lang/Class' inited in init_vm.rs\n*/\npub fn create_delayed_mirrors() {\n    let names: Vec<String> = {\n        let mirros = DELAYED_MIRROS.read().unwrap();\n        mirros.clone()\n    };\n\n    {\n        let mut s = MIRROR_STATE.write().unwrap();\n        *s = ClassMirrorState::Fixed;\n    }\n\n    for name in names {\n        if name.len() > 2 {\n            //java.lang.XXX\n            let target = require_class3(None, name.as_bytes()).unwrap();\n            create_mirror(target);\n        } else {\n            let is_prim_ary = name.as_bytes()[0] == b'[';\n            let (vt, target) = if is_prim_ary {\n                let vt = ValueType::from(&name.as_bytes()[1]);\n                let target = require_class3(None, name.as_bytes()).unwrap();\n                (vt, Some(target))\n            } else {\n                (ValueType::from(&name.as_bytes()[0]), None)\n            };\n\n            let mirror = Oop::new_prim_mirror(vt, target.clone());\n            if is_prim_ary {\n                let target = target.unwrap();\n                let cls = target.get_mut_class();\n                //                warn!(\"set_mirror name={}\", String::from_utf8_lossy(cls.name.as_slice()));\n                cls.set_mirror(mirror.clone());\n            }\n\n            let mut mirrors = PRIM_MIRROS.write().unwrap();\n            mirrors.insert(name.to_string(), mirror);\n        }\n    }\n}\n\n/*\ncalled after 'java/lang/Class' inited in init_vm.rs\n*/\npub fn create_delayed_ary_mirrors() {\n    let classes: Vec<ClassRef> = {\n        let mirros = DELAYED_ARY_MIRROS.read().unwrap();\n        mirros.clone()\n    };\n\n    for cls in classes {\n        let value_type = {\n            let cls = cls.get_class();\n            match &cls.kind {\n                oop::class::ClassKind::ObjectArray(obj_ary) => obj_ary.value_type,\n                oop::class::ClassKind::TypeArray(typ_ary) => typ_ary.value_type,\n                _ => unreachable!(),\n            }\n        };\n        let mirror = Oop::new_ary_mirror(cls.clone(), value_type);\n        let cls = cls.get_mut_class();\n        cls.set_mirror(mirror);\n    }\n}\n\nfn jvm_registerNatives(_env: JNIEnv, _args: &[Oop]) -> JNIResult {\n    Ok(None)\n}\n\nfn jvm_desiredAssertionStatus0(_env: JNIEnv, _args: &[Oop]) -> JNIResult {\n    Ok(Some(Oop::new_int(0)))\n}\n\nfn jvm_getPrimitiveClass(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let v = args.get(0).unwrap();\n    let v = OopPtr::java_lang_string(v.extract_ref());\n    match SIGNATURE_DIC.get(v.as_str()) {\n        Some(&s) => Ok(get_primitive_class_mirror(s)),\n        _ => unreachable!(\"Unknown primitive type: {}\", v),\n    }\n}\n\nfn jvm_getDeclaredFields0(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    //parse args\n    let mirror_target = {\n        let arg0 = args.get(0).unwrap();\n        extract_mirror_target(arg0)\n    };\n\n    let public_only = {\n        let arg1 = args.get(1).unwrap();\n        arg1.extract_int() == 1\n    };\n\n    //fixme: super fields\n    //obtain inst&static fields\n    let (inst_fields, static_fields) = {\n        let inst = mirror_target.extract_inst();\n        (inst.inst_fields.clone(), inst.static_fields.clone())\n    };\n\n    //build fields ary\n    let mut fields = Vec::new();\n    for (_, it) in inst_fields {\n        if public_only && !it.field.is_public() {\n            continue;\n        }\n\n        let v = common::reflect::new_field(it);\n        fields.push(v);\n    }\n\n    for (_, it) in static_fields {\n        if public_only && !it.field.is_public() {\n            continue;\n        }\n\n        let v = common::reflect::new_field(it);\n        fields.push(v);\n    }\n\n    //build oop field ar\n    let ary_cls = require_class3(None, b\"[Ljava/lang/reflect/Field;\").unwrap();\n    Ok(Some(Oop::new_ref_ary2(ary_cls, fields)))\n}\n\nfn jvm_getName0(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let (target, vt) = {\n        let arg0 = args.get(0).unwrap();\n        let rf = arg0.extract_ref();\n        let mirror = rf.extract_mirror();\n        (mirror.target.clone(), mirror.value_type)\n    };\n    let name = {\n        match target {\n            Some(target) => {\n                let cls = target.get_class();\n                Vec::from(cls.name.as_slice())\n            }\n            None => {\n                let v = vt.get_primitive_name();\n                Vec::from(v)\n            }\n        }\n    };\n\n    let name = unsafe { std::str::from_utf8_unchecked(name.as_slice()) };\n    let name = name.replace(\"/\", \".\");\n    let v = util::oop::new_java_lang_string2(&name);\n    Ok(Some(v))\n}\n\nfn jvm_forName0(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let arg0 = args.get(0).unwrap();\n    let java_name = {\n        let rf = arg0.extract_ref();\n        OopPtr::java_lang_string(rf)\n    };\n    let initialize = {\n        let arg1 = args.get(1).unwrap();\n        arg1.extract_int() != 0\n    };\n    let java_cls_loader = args.get(2).unwrap();\n    {\n        match java_cls_loader {\n            Oop::Null => (),\n            _ => unimplemented!(\"app class loader, unimpl\"),\n        }\n    }\n\n    let _caller_mirror = args.get(3).unwrap();\n\n    if java_name.contains('/') {\n        let msg = Some(java_name);\n        let ex = runtime::exception::new(cls_consts::J_CLASS_NOT_FOUND, msg);\n        return Err(ex);\n    }\n\n    let java_name = java_name.replace(\".\", \"/\");\n    let cls = {\n        if java_name == \"sun/nio/cs/ext/ExtendedCharsets\" {\n            //fixme: skip, cause jvm start very slow\n            None\n        } else {\n            require_class3(None, java_name.as_bytes())\n        }\n    };\n\n    match cls {\n        Some(cls) => {\n            oop::class::init_class(&cls);\n            if initialize {\n                oop::class::init_class_fully(&cls);\n            }\n\n            let mirror = cls.get_class().get_mirror();\n            Ok(Some(mirror))\n        }\n        None => {\n            // error!(\"forName0, NotFound: {}\", java_name);\n            let msg = Some(java_name);\n            let ex = runtime::exception::new(cls_consts::J_CLASS_NOT_FOUND, msg);\n            Err(ex)\n        }\n    }\n}\n\nfn jvm_isPrimitive(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let v = args.get(0).unwrap();\n    let v = {\n        let rf = v.extract_ref();\n        let mirror = rf.extract_mirror();\n        if mirror.target.is_none() {\n            1\n        } else {\n            0\n        }\n    };\n    Ok(Some(Oop::new_int(v)))\n}\n\nfn jvm_isAssignableFrom(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let l = args.get(0).unwrap();\n    let r = args.get(1).unwrap();\n\n    let (lt, ltyp) = {\n        let rf = l.extract_ref();\n        let mirror = rf.extract_mirror();\n        (mirror.target.clone(), mirror.value_type)\n    };\n\n    let (rt, rtyp) = {\n        let rf = r.extract_ref();\n        let mirror = rf.extract_mirror();\n        (mirror.target.clone(), mirror.value_type)\n    };\n\n    let v = if lt.is_none() && rt.is_none() {\n        if ltyp == rtyp {\n            1\n        } else {\n            0\n        }\n    } else {\n        let lt = lt.unwrap();\n        let rt = rt.unwrap();\n        if runtime::cmp::instance_of(rt, lt) {\n            1\n        } else {\n            0\n        }\n    };\n\n    Ok(Some(Oop::new_int(v)))\n}\n\nfn jvm_isInterface(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let v = args.get(0).unwrap();\n    let v = {\n        let rf = v.extract_ref();\n        let mirror = rf.extract_mirror();\n        match &mirror.target {\n            Some(target) => {\n                if target.get_class().is_interface() {\n                    1\n                } else {\n                    0\n                }\n            }\n            None => 0,\n        }\n    };\n\n    Ok(Some(Oop::new_int(v)))\n}\n\nfn jvm_getDeclaredConstructors0(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    //parse args\n    let mirror_target = {\n        let arg0 = args.get(0).unwrap();\n        extract_mirror_target(arg0)\n    };\n    let public_only = args.get(1).unwrap().extract_int() == 1;\n    get_declared_method_helper(mirror_target, public_only, true)\n}\n\npub fn jvm_getModifiers(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let v = args.get(0).unwrap();\n    let v = {\n        let rf = v.extract_ref();\n        let mirror = rf.extract_mirror();\n        match &mirror.target {\n            Some(target) => {\n                let mut acc_flags = target.get_class().acc_flags;\n\n                //use access_flags in InnerClasses Attribute\n                //don't know why. just read the JDK codes\n                let inst = target.extract_inst();\n                let this_class = inst.class_file.this_class;\n                match &inst.inner_classes {\n                    Some(inner_classes) => {\n                        for it in inner_classes {\n                            if it.inner_class_info_index == 0 {\n                                continue;\n                            }\n\n                            if it.inner_class_info_index == this_class {\n                                acc_flags = it.inner_class_access_flags;\n                            }\n                        }\n                    }\n                    None => {}\n                }\n\n                acc_flags\n            }\n            None => acc::ACC_ABSTRACT | acc::ACC_FINAL | acc::ACC_PUBLIC,\n        }\n    };\n\n    Ok(Some(Oop::new_int(v as i32)))\n}\n\nfn jvm_getSuperclass(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let arg0 = args.get(0).unwrap();\n    let rf = arg0.extract_ref();\n    let mirror = rf.extract_mirror();\n    match &mirror.target {\n        Some(target) => {\n            let cls = target.get_class();\n            match &cls.super_class {\n                Some(super_cls) => {\n                    let cls = super_cls.get_class();\n                    let mirror = cls.get_mirror();\n                    Ok(Some(mirror))\n                }\n                None => Ok(Some(Oop::Null)),\n            }\n        }\n        None => Ok(Some(Oop::Null)),\n    }\n}\n\nfn jvm_isArray(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let arg0 = args.get(0).unwrap();\n\n    let mirror_cls = {\n        let rf = arg0.extract_ref();\n        let mirror = rf.extract_mirror();\n        match &mirror.target {\n            Some(target) => target.clone(),\n            None => return Ok(Some(Oop::new_int(0))),\n        }\n    };\n\n    let cls = mirror_cls.get_class();\n    let v = match cls.get_class_kind_type() {\n        oop::class::ClassKindType::Instance => 0,\n        _ => 1,\n    };\n\n    Ok(Some(Oop::new_int(v)))\n}\n\nfn jvm_getComponentType(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let arg0 = args.get(0).unwrap();\n    let cls = {\n        let rf = arg0.extract_ref();\n        let mirror = rf.extract_mirror();\n        mirror.target.clone().unwrap()\n    };\n    let cls = cls.get_class();\n    let v = match &cls.kind {\n        oop::class::ClassKind::TypeArray(type_ary_cls) => {\n            let vt = type_ary_cls.value_type.into();\n            let key = unsafe { std::str::from_utf8_unchecked(vt) };\n            let mirrors = PRIM_MIRROS.read().unwrap();\n            mirrors.get(key).cloned()\n        }\n        oop::class::ClassKind::ObjectArray(obj_ary_cls) => {\n            let component = obj_ary_cls.component.clone().unwrap();\n            let cls = component.get_class();\n            Some(cls.get_mirror())\n        }\n        _ => unreachable!(),\n    };\n    Ok(v)\n}\n\nfn jvm_getEnclosingMethod0(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let arg0 = args.get(0).unwrap();\n    let target = {\n        let rf = arg0.extract_ref();\n        let ptr = rf.get_raw_ptr();\n        unsafe {\n            match &(*ptr).v {\n                oop::RefKind::Mirror(mirror) => mirror.target.clone(),\n                _ => return Ok(Some(Oop::Null)),\n            }\n        }\n    };\n\n    let (cls_file, em) = match target {\n        Some(target) => {\n            let cls = target.get_class();\n            match &cls.kind {\n                ClassKind::Instance(cls) => match &cls.enclosing_method {\n                    Some(em) => (cls.class_file.clone(), em.clone()),\n                    None => return Ok(Some(Oop::Null)),\n                },\n                _ => return Ok(Some(Oop::Null)),\n            }\n        }\n        None => return Ok(Some(Oop::Null)),\n    };\n\n    //push EnclosingMethod class mirror\n    if em.class_index == 0 {\n        panic!();\n    }\n    let em_class = require_class2(em.class_index, &cls_file.cp).unwrap();\n    let em_class_mirror = {\n        let cls = em_class.get_class();\n        cls.get_mirror()\n    };\n    let mut elms = Vec::with_capacity(3);\n    elms.push(em_class_mirror);\n\n    //push EnclosingMethod name&desc\n    if em.method_index != 0 {\n        let (name, desc) = constant_pool::get_name_and_type(&cls_file.cp, em.method_index as usize);\n        let name = unsafe { std::str::from_utf8_unchecked(name.as_slice()) };\n        let desc = unsafe { std::str::from_utf8_unchecked(desc.as_slice()) };\n\n        elms.push(util::oop::new_java_lang_string2(name));\n        elms.push(util::oop::new_java_lang_string2(desc));\n    } else {\n        elms.push(Oop::Null);\n        elms.push(Oop::Null);\n    }\n\n    let ary = require_class3(None, b\"[Ljava/lang/Object;\").unwrap();\n    let ary = Oop::new_ref_ary2(ary, elms);\n\n    Ok(Some(ary))\n}\n\nfn jvm_getDeclaringClass0(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let arg0 = args.get(0).unwrap();\n    let target = {\n        let rf = arg0.extract_ref();\n        let ptr = rf.get_raw_ptr();\n        unsafe {\n            match &(*ptr).v {\n                oop::RefKind::Mirror(mirror) => mirror.target.clone(),\n                _ => return Ok(Some(Oop::Null)),\n            }\n        }\n    };\n\n    let (cls_file, target, inner_classes) = match target {\n        Some(target) => {\n            let cls = target.get_class();\n            match &cls.kind {\n                ClassKind::Instance(cls) => match &cls.inner_classes {\n                    Some(inner_classes) => (\n                        cls.class_file.clone(),\n                        target.clone(),\n                        inner_classes.clone(),\n                    ),\n                    None => return Ok(Some(Oop::Null)),\n                },\n                _ => return Ok(Some(Oop::Null)),\n            }\n        }\n        None => return Ok(Some(Oop::Null)),\n    };\n\n    for it in inner_classes.iter() {\n        if it.inner_class_info_index == 0 {\n            continue;\n        }\n\n        let inner_class = require_class2(it.inner_class_info_index, &cls_file.cp).unwrap();\n\n        if Arc::ptr_eq(&inner_class, &target) {\n            return if it.outer_class_info_index == 0 {\n                Ok(Some(Oop::Null))\n            } else {\n                let outer_class = require_class2(it.outer_class_info_index, &cls_file.cp).unwrap();\n                let v = outer_class.get_class();\n                Ok(Some(v.get_mirror()))\n            };\n        }\n    }\n\n    Ok(Some(Oop::Null))\n}\n\nfn jvm_isInstance(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let arg0 = args.get(0).unwrap();\n    let arg1 = args.get(1).unwrap();\n\n    let target_cls = {\n        let rf = arg0.extract_ref();\n        let ptr = rf.get_raw_ptr();\n        unsafe {\n            match &(*ptr).v {\n                oop::RefKind::Inst(inst) => inst.class.clone(),\n                oop::RefKind::Mirror(mirror) => mirror.target.clone().unwrap(),\n                _ => unreachable!(),\n            }\n        }\n    };\n    let obj_cls = {\n        let rf = arg1.extract_ref();\n        let inst = rf.extract_inst();\n        inst.class.clone()\n    };\n\n    let v = if runtime::cmp::instance_of(obj_cls, target_cls) {\n        1\n    } else {\n        0\n    };\n\n    Ok(Some(Oop::new_int(v)))\n}\n\nfn jvm_getDeclaredMethods0(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    //parse args\n    let mirror_target = {\n        let arg0 = args.get(0).unwrap();\n        extract_mirror_target(arg0)\n    };\n    let public_only = args.get(1).unwrap().extract_int() == 1;\n    get_declared_method_helper(mirror_target, public_only, false)\n}\n\nfn jvm_getInterfaces0(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let mirror = {\n        let arg0 = args.get(0).unwrap();\n        extract_mirror_target(arg0)\n    };\n\n    let v = mirror.get_class();\n    let elms = match &v.kind {\n        oop::ClassKind::Instance(inst) => {\n            let mut elms = Vec::with_capacity(inst.class_file.interfaces.len());\n            let cp = &inst.class_file.cp;\n            inst.class_file.interfaces.iter().for_each(|it| {\n                let cls = require_class2(*it, cp).unwrap();\n                let cls = cls.get_class();\n                elms.push(cls.get_mirror());\n            });\n\n            elms\n        }\n        ClassKind::ObjectArray(_ary) => {\n            let cls_cloneable = require_class3(None, cls_consts::J_CLONEABLE).unwrap();\n            let cls_serializable = require_class3(None, cls_consts::J_SERIALIZABLE).unwrap();\n            let mut elms = Vec::with_capacity(2);\n\n            {\n                let cls = cls_cloneable.get_class();\n                elms.push(cls.get_mirror());\n            }\n\n            {\n                let cls = cls_serializable.get_class();\n                elms.push(cls.get_mirror());\n            }\n\n            elms\n        }\n        ClassKind::TypeArray(_) => unimplemented!(\"type array getInterfaces0\"),\n    };\n\n    let clazz = require_class3(None, b\"[Ljava/lang/Class;\").unwrap();\n    let ary = Oop::new_ref_ary2(clazz, elms);\n\n    Ok(Some(ary))\n}\n\nfn jvm_getRawAnnotations(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let cls = args.get(0).unwrap();\n    let annotations = match cls {\n        Oop::Ref(rf) => {\n            let mirror = rf.extract_mirror();\n            let cls = mirror.target.clone().unwrap();\n            let cls = cls.get_class();\n            let raw = cls.get_annotation();\n            match raw {\n                Some(raw) => Oop::new_byte_ary2(raw.to_vec()),\n                None => Oop::Null,\n            }\n        }\n        _ => Oop::Null,\n    };\n\n    Ok(Some(annotations))\n}\n\nfn jvm_getConstantPool(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let this = args.get(0).unwrap();\n    let cp_oop = match this {\n        Oop::Ref(_rf) => {\n            let cp_cls = require_class3(None, b\"sun/reflect/ConstantPool\").unwrap();\n            let cp_oop = Oop::new_inst(cp_cls.clone());\n\n            let cls = cp_cls.get_class();\n            let fid =\n                cls.get_field_id(&util::S_CONSTANT_POOL_OOP, &util::S_JAVA_LANG_OBJECT, false);\n            //todo: reimpl maybe, create one JNIHandles, like jdk\n            Class::put_field_value(cp_oop.extract_ref(), fid, this.clone());\n\n            cp_oop\n        }\n        _ => Oop::Null,\n    };\n\n    Ok(Some(cp_oop))\n}\n\nfn jvm_getDeclaredClasses0(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let this = args.get(0).unwrap();\n    let target_clz = extract_mirror_target(this);\n\n    let array_class = require_class3(None, b\"[Ljava/lang/Class;\").unwrap();\n\n    let target_class = target_clz.get_class();\n    let v = match &target_class.kind {\n        ClassKind::Instance(inst) => {\n            let cp = &inst.class_file.cp;\n            match &inst.inner_classes {\n                Some(inner_classes) => {\n                    let this_class = inst.class_file.this_class;\n                    let mut inners = Vec::with_capacity(inner_classes.len());\n                    for it in inner_classes {\n                        if it.outer_class_info_index == this_class {\n                            let inner_clz = require_class2(it.inner_class_info_index, cp).unwrap();\n                            let v = inner_clz.get_class().get_mirror();\n                            inners.push(v);\n                        }\n                    }\n\n                    Oop::new_ref_ary2(array_class, inners)\n                }\n                _ => Oop::new_ref_ary(array_class, 0),\n            }\n        }\n        _ => Oop::new_ref_ary(array_class, 0),\n    };\n\n    Ok(Some(v))\n}\n\nfn jvm_getGenericSignature0(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let this = args.get(0).unwrap();\n    let v = match this {\n        Oop::Ref(rf) => {\n            let ptr = rf.get_raw_ptr();\n            unsafe {\n                let mirror = (*ptr).v.extract_mirror();\n                let vt = mirror.value_type;\n                if vt == ValueType::OBJECT {\n                    let target = mirror.target.clone().unwrap();\n                    let cls = target.get_class();\n                    let sig = cls.get_attr_signatrue();\n                    sig.map_or(Oop::Null, |v| {\n                        let sig = std::str::from_utf8_unchecked(v.as_slice());\n                        util::oop::new_java_lang_string2(sig)\n                    })\n                } else {\n                    Oop::Null\n                }\n            }\n        }\n        _ => unreachable!(),\n    };\n\n    Ok(Some(v))\n}\n\nfn get_declared_method_helper(\n    mirror_target: ClassRef,\n    public_only: bool,\n    want_constructor: bool,\n) -> JNIResult {\n    //fixme: super methods\n    let selected_methods = {\n        let cls = mirror_target.get_class();\n        match &cls.kind {\n            oop::class::ClassKind::Instance(inst) => {\n                fn chooser1(want_constructor: bool, name: &[u8]) -> bool {\n                    if want_constructor {\n                        name == b\"<init>\"\n                    } else {\n                        name != b\"<init>\"\n                    }\n                }\n\n                fn chooser2(want_constructor: bool, m: &MethodIdRef) -> bool {\n                    if want_constructor {\n                        m.method.name.as_slice() == b\"<init>\" && !m.method.is_static()\n                    } else {\n                        m.method.name.as_slice() != b\"<init>\"\n                    }\n                }\n\n                let mut selected_methods = Vec::new();\n                for (k, m) in inst.all_methods.iter() {\n                    if !chooser1(want_constructor, k.0.as_slice()) {\n                        continue;\n                    }\n\n                    if chooser2(want_constructor, &m) && (!public_only || m.method.is_public()) {\n                        selected_methods.push(m.clone());\n                    }\n                }\n\n                selected_methods\n            }\n            oop::class::ClassKind::ObjectArray(_ary) => vec![],\n            _ => unreachable!(\"{:?}\", mirror_target),\n        }\n    };\n\n    //build methods ary\n    let mut methods = Vec::with_capacity(selected_methods.len());\n    for m in selected_methods {\n        let v = if want_constructor {\n            common::reflect::new_method_ctor(m)\n        } else {\n            common::reflect::new_method_normal(m)\n        };\n\n        methods.push(v);\n    }\n\n    //build oop methods ary\n    let ary_cls = if want_constructor {\n        require_class3(None, b\"[Ljava/lang/reflect/Constructor;\").unwrap()\n    } else {\n        require_class3(None, b\"[Ljava/lang/reflect/Method;\").unwrap()\n    };\n\n    Ok(Some(Oop::new_ref_ary2(ary_cls, methods)))\n}\n\nfn extract_mirror_target(v: &Oop) -> ClassRef {\n    let rf = v.extract_ref();\n    let mirror = rf.extract_mirror();\n    mirror.target.clone().unwrap()\n}\n"
  },
  {
    "path": "crates/vm/src/native/java_lang_ClassLoader.rs",
    "content": "#![allow(non_snake_case)]\n\nuse crate::native::{new_fn, JNIEnv, JNINativeMethod, JNIResult};\nuse crate::oop::{self, Oop, OopPtr};\nuse crate::runtime;\nuse crate::util;\n\npub fn get_native_methods() -> Vec<JNINativeMethod> {\n    vec![\n        new_fn(\"registerNatives\", \"()V\", Box::new(jvm_registerNatives)),\n        new_fn(\n            \"findBuiltinLib\",\n            \"(Ljava/lang/String;)Ljava/lang/String;\",\n            Box::new(jvm_findBuiltinLib),\n        ),\n        new_fn(\n            \"findLoadedClass0\",\n            \"(Ljava/lang/String;)Ljava/lang/Class;\",\n            Box::new(jvm_findLoadedClass0),\n        ),\n        new_fn(\n            \"findBootstrapClass\",\n            \"(Ljava/lang/String;)Ljava/lang/Class;\",\n            Box::new(jvm_findBootstrapClass),\n        ),\n    ]\n}\n\nfn jvm_registerNatives(_env: JNIEnv, _args: &[Oop]) -> JNIResult {\n    Ok(None)\n}\n\nfn jvm_findBuiltinLib(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let name = args.get(0).unwrap();\n    let name = OopPtr::java_lang_string(name.extract_ref());\n    info!(\"findBuiltinLib: {}\", name);\n    Ok(None)\n}\n\nfn jvm_findLoadedClass0(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let name = args.get(1).unwrap();\n    let name = OopPtr::java_lang_string(name.extract_ref());\n    info!(\"findLoadedClass0: {}\", name);\n    let name = name.replace(\".\", util::FILE_SEP);\n    let v = match runtime::sys_dic_find(name.as_bytes()) {\n        Some(cls) => {\n            let cls = cls.get_class();\n            cls.get_mirror()\n        }\n        None => Oop::Null,\n    };\n    Ok(Some(v))\n}\n\n// fixme: Is this correct? uncertain\nfn jvm_findBootstrapClass(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    info!(\"findBootstrapClass\");\n    jvm_findLoadedClass0(_env, args)\n}\n"
  },
  {
    "path": "crates/vm/src/native/java_lang_Double.rs",
    "content": "#![allow(non_snake_case)]\n\nuse crate::native::{new_fn, JNIEnv, JNINativeMethod, JNIResult};\nuse crate::oop::Oop;\n\npub fn get_native_methods() -> Vec<JNINativeMethod> {\n    vec![\n        new_fn(\n            \"doubleToRawLongBits\",\n            \"(D)J\",\n            Box::new(jvm_doubleToRawLongBits),\n        ),\n        new_fn(\"longBitsToDouble\", \"(J)D\", Box::new(jvm_longBitsToDouble)),\n    ]\n}\n\nfn jvm_doubleToRawLongBits(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let v = args.get(0).unwrap().extract_double();\n    let v = v.to_bits().to_be_bytes();\n    let v = i64::from_be_bytes(v);\n    Ok(Some(Oop::new_long(v)))\n}\n\nfn jvm_longBitsToDouble(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let v = args.get(0).unwrap().extract_long();\n    let v = v.to_be_bytes();\n    let v = f64::from_be_bytes(v);\n    Ok(Some(Oop::new_double(v)))\n}\n"
  },
  {
    "path": "crates/vm/src/native/java_lang_Float.rs",
    "content": "#![allow(non_snake_case)]\n\nuse crate::native::{new_fn, JNIEnv, JNINativeMethod, JNIResult};\nuse crate::oop::Oop;\n\npub fn get_native_methods() -> Vec<JNINativeMethod> {\n    vec![new_fn(\n        \"floatToRawIntBits\",\n        \"(F)I\",\n        Box::new(jvm_floatToRawIntBits),\n    )]\n}\n\nfn jvm_floatToRawIntBits(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let v = args.get(0).unwrap().extract_float();\n    let v = v.to_bits().to_be_bytes();\n    let v = i32::from_be_bytes(v);\n    Ok(Some(Oop::new_int(v)))\n}\n"
  },
  {
    "path": "crates/vm/src/native/java_lang_Object.rs",
    "content": "#![allow(non_snake_case)]\n\nuse crate::native::{new_fn, JNIEnv, JNINativeMethod, JNIResult};\nuse crate::oop::{self, Oop};\nuse std::time::Duration;\n\npub fn get_native_methods() -> Vec<JNINativeMethod> {\n    vec![\n        new_fn(\"registerNatives\", \"()V\", Box::new(jvm_registerNatives)),\n        new_fn(\"hashCode\", \"()I\", Box::new(jvm_hashCode)),\n        new_fn(\"clone\", \"()Ljava/lang/Object;\", Box::new(jvm_clone)),\n        new_fn(\"getClass\", \"()Ljava/lang/Class;\", Box::new(jvm_getClass)),\n        new_fn(\"notifyAll\", \"()V\", Box::new(jvm_notifyAll)),\n        new_fn(\"wait\", \"(J)V\", Box::new(jvm_wait)),\n    ]\n}\n\nfn jvm_registerNatives(_env: JNIEnv, _args: &[Oop]) -> JNIResult {\n    Ok(None)\n}\n\npub fn jvm_hashCode(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let v = args.get(0).unwrap();\n    let v = v.hash_code();\n    let v = Oop::new_int(v);\n    Ok(Some(v))\n}\n\nfn jvm_clone(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    //    let java_lang_Cloneable = require_class3(None, b\"java/lang/Cloneable\").unwrap();\n    let this_obj = args.get(0).unwrap();\n    Ok(Some(this_obj.clone()))\n}\n\nfn jvm_getClass(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let v = args.get(0).unwrap();\n    let mirror = {\n        let rf = v.extract_ref();\n        let ptr = rf.get_raw_ptr();\n        unsafe {\n            match &(*ptr).v {\n                oop::RefKind::Inst(inst) => {\n                    let cls = inst.class.get_class();\n                    cls.get_mirror()\n                }\n                oop::RefKind::Array(ary) => ary.class.get_class().get_mirror(),\n                oop::RefKind::Mirror(_mirror) => v.clone(),\n                t => unimplemented!(\"t = {:?}\", t),\n            }\n        }\n    };\n    Ok(Some(mirror))\n}\n\nfn jvm_notifyAll(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let this = args.get(0).unwrap();\n    let rf = this.extract_ref();\n    rf.notify_all();\n    Ok(None)\n}\n\nfn jvm_wait(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let this = args.get(0).unwrap();\n    let millis = args.get(1).unwrap().extract_long();\n\n    let rf = this.extract_ref();\n    if millis == 0 {\n        rf.wait();\n    } else {\n        rf.wait_timeout(Duration::from_millis(millis as u64));\n    }\n\n    Ok(None)\n}\n"
  },
  {
    "path": "crates/vm/src/native/java_lang_Runtime.rs",
    "content": "#![allow(non_snake_case)]\n\nuse crate::native::{new_fn, JNIEnv, JNINativeMethod, JNIResult};\nuse crate::oop::Oop;\n\npub fn get_native_methods() -> Vec<JNINativeMethod> {\n    vec![\n        new_fn(\n            \"availableProcessors\",\n            \"()I\",\n            Box::new(jvm_availableProcessors),\n        ),\n        new_fn(\"gc\", \"()V\", Box::new(jvm_gc)),\n    ]\n}\n\n//fixme:\nfn jvm_availableProcessors(_env: JNIEnv, _args: &[Oop]) -> JNIResult {\n    Ok(Some(Oop::new_int(1)))\n}\n\nfn jvm_gc(_env: JNIEnv, _args: &[Oop]) -> JNIResult {\n    Ok(None)\n}\n"
  },
  {
    "path": "crates/vm/src/native/java_lang_String.rs",
    "content": "#![allow(non_snake_case)]\n\nuse crate::native::{new_fn, JNIEnv, JNINativeMethod, JNIResult};\nuse crate::oop::Oop;\n\npub fn get_native_methods() -> Vec<JNINativeMethod> {\n    vec![new_fn(\n        \"intern\",\n        \"()Ljava/lang/String;\",\n        Box::new(jvm_intern),\n    )]\n}\n\nfn jvm_intern(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let v = args.get(0).unwrap();\n    Ok(Some(v.clone()))\n}\n"
  },
  {
    "path": "crates/vm/src/native/java_lang_System.rs",
    "content": "#![allow(non_snake_case)]\n\nuse crate::native::{self, new_fn, JNIEnv, JNINativeMethod, JNIResult};\nuse crate::oop::{self, Oop, OopPtr};\nuse crate::runtime::{self, thread, JavaCall};\nuse crate::{new_br, util};\nuse std::sync::Arc;\nuse std::time::SystemTime;\n\npub fn get_native_methods() -> Vec<JNINativeMethod> {\n    vec![\n        new_fn(\n            \"arraycopy\",\n            \"(Ljava/lang/Object;ILjava/lang/Object;II)V\",\n            Box::new(jvm_arraycopy),\n        ),\n        new_fn(\"registerNatives\", \"()V\", Box::new(jvm_registerNatives)),\n        new_fn(\n            \"initProperties\",\n            \"(Ljava/util/Properties;)Ljava/util/Properties;\",\n            Box::new(jvm_initProperties),\n        ),\n        new_fn(\"setIn0\", \"(Ljava/io/InputStream;)V\", Box::new(jvm_setIn0)),\n        new_fn(\"setOut0\", \"(Ljava/io/PrintStream;)V\", Box::new(jvm_setOut0)),\n        new_fn(\"setErr0\", \"(Ljava/io/PrintStream;)V\", Box::new(jvm_setErr0)),\n        new_fn(\n            \"mapLibraryName\",\n            \"(Ljava/lang/String;)Ljava/lang/String;\",\n            Box::new(jvm_mapLibraryName),\n        ),\n        new_fn(\n            \"loadLibrary\",\n            \"(Ljava/lang/String;)V\",\n            Box::new(jvm_loadLibrary),\n        ),\n        new_fn(\n            \"identityHashCode\",\n            \"(Ljava/lang/Object;)I\",\n            Box::new(jvm_identityHashCode),\n        ),\n        new_fn(\"nanoTime\", \"()J\", Box::new(jvm_nanoTime)),\n        new_fn(\"currentTimeMillis\", \"()J\", Box::new(jvm_currentTimeMillis)),\n        //Note: just for debug\n        //        new_fn(\"getProperty\", \"(Ljava/lang/String;)Ljava/lang/String;\", Box::new(jvm_getProperty)),\n    ]\n}\n\nfn jvm_registerNatives(_env: JNIEnv, _args: &[Oop]) -> JNIResult {\n    Ok(None)\n}\n\nfn jvm_arraycopy(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let src = args.get(0).unwrap();\n    let src_pos = args.get(1).unwrap().extract_int();\n    let dest = args.get(2).unwrap();\n    let dest_pos = args.get(3).unwrap().extract_int();\n    let length = args.get(4).unwrap().extract_int();\n\n    //todo: do check & throw exception\n\n    if length == 0 {\n        return Ok(None);\n    }\n\n    let is_same_obj = OopPtr::is_eq(src, dest);\n\n    if is_same_obj {\n        arraycopy_same_obj(\n            src.extract_ref(),\n            src_pos as usize,\n            dest_pos as usize,\n            length as usize,\n        );\n    } else {\n        arraycopy_diff_obj(\n            src.extract_ref(),\n            src_pos as usize,\n            dest.extract_ref(),\n            dest_pos as usize,\n            length as usize,\n        );\n    }\n\n    Ok(None)\n}\n\nfn jvm_initProperties(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    //fixme:\n    let props = vec![\n        (\"file.encoding.pkg\", \"sun.io\"),\n        (\"file.encoding\", \"US-ASCII\"),\n        (\"file.separator\", util::FILE_SEP),\n        (\"java.class.path\", \".\"),\n        (\"java.class.version\", \"52.0\"),\n        (\"java.security.egd\", \"file:/dev/random\"),\n        // (\"java.security.debug\", \"all\"),\n        // (\"java.security.auth.debug\", \"all\"),\n        (\"java.specification.version\", \"1.8\"),\n        (\"java.specification.name\", \"Java Platform API Specification\"),\n        (\"java.specification.vendor\", \"Oracle Corporation\"),\n        (\"java.vendor\", \"Chuan\"),\n        (\"java.vendor.url\", \"https://github.com/douchuan/jvm\"),\n        (\"java.vendor.url.bug\", \"https://github.com/douchuan/jvm\"),\n        (\"java.version\", \"1.8\"),\n        (\"line.separator\", util::LINE_SEP),\n        (\"os.arch\", \"x86_64\"),\n        (\"os.name\", \"Mac OS X\"),\n        (\"os.version\", \"18.7.0\"),\n        (\"path.separator\", util::PATH_SEP),\n        (\"sun.arch.data.model\", \"64\"),\n        (\"sun.cpu.endian\", \"little\"),\n        (\"sun.cpu.isalist\", \"\"),\n        // (\"sun.misc.URLClassPath.debug\", \"true\"),\n        // (\"sun.misc.URLClassPath.debugLookupCache\", \"true\"),\n        (\"sun.stdout.encoding\", \"UTF-8\"),\n        (\"sun.stderr.encoding\", \"UTF-8\"),\n        (\"user.language\", \"en\"),\n        (\"user.name\", \"chuan\"),\n        (\"user.region\", \"US\"),\n        //        (\"java.security.manager\", \"\"),\n        //        (\"sun.jnu.encoding\", \"UTF-8\"),\n        //        (\"sun.io.unicode.encoding\", \"UnicodeBig\"),\n    ];\n\n    let props_oop = args.get(0).unwrap();\n    for (k, v) in props.iter() {\n        put_props_kv(props_oop, k, v);\n    }\n\n    //user.dir\n    let v = std::env::current_dir().expect(\"current_dir failed\");\n    let v = v.to_str().expect(\"current_dir to_str faield\");\n    put_props_kv(props_oop, \"user.dir\", v);\n\n    //java.io.tmpdir\n    let v = std::env::temp_dir();\n    let v = v.to_str().expect(\"temp_dir to_str failed\");\n    put_props_kv(props_oop, \"java.io.tmpdir\", v);\n\n    //user.home\n    let v = dirs::home_dir().expect(\"get home_dir failed\");\n    let v = v.to_str().expect(\"home_dir to_str failed\");\n    put_props_kv(props_oop, \"user.home\", v);\n\n    //JAVA_HOME\n    let v = std::env::var(\"JAVA_HOME\").expect(\"Please Setup JAVA_HOME env\");\n    put_props_kv(props_oop, \"java.home\", v.as_str());\n\n    //test.src for jdk/test/java/lang/Character/CheckProp.java\n    if let Ok(v) = std::env::var(\"TEST_SRC\") {\n        put_props_kv(props_oop, \"test.src\", v.as_str());\n    }\n\n    if thread::is_meet_ex() {\n        unreachable!(\"jvm_initProperties meet ex\");\n    }\n\n    Ok(Some(props_oop.clone()))\n}\n\nfn put_props_kv(props: &Oop, k: &str, v: &str) {\n    //todo: optimize me\n    let cls = {\n        let rf = props.extract_ref();\n        let inst = rf.extract_inst();\n        inst.class.clone()\n    };\n\n    let mir = {\n        let cls = cls.get_class();\n        cls.get_virtual_method(\n            &new_br(\"put\"),\n            &new_br(\"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;\"),\n        )\n        .unwrap()\n    };\n\n    let k = util::oop::new_java_lang_string2(k);\n    let v = util::oop::new_java_lang_string2(v);\n\n    let args = vec![props.clone(), k, v];\n\n    let mut jc = JavaCall::new_with_args(mir, args);\n    let area = runtime::DataArea::new(1);\n    jc.invoke(Some(&area), false);\n}\n\nfn jvm_setIn0(env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let v = args.get(0).unwrap();\n    let cls = env.read().unwrap().class.clone();\n    let cls = cls.get_mut_class();\n    let id = cls.get_field_id(&util::S_IN, &util::S_JAVA_IO_INPUT_STREAM, true);\n    cls.put_static_field_value(id, v.clone());\n    Ok(None)\n}\n\nfn jvm_setOut0(env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let v = args.get(0).unwrap();\n    let cls = env.read().unwrap().class.clone();\n    let cls = cls.get_mut_class();\n    let id = cls.get_field_id(&util::S_OUT, &util::S_JAVA_IO_PRINT_STREAM, true);\n    cls.put_static_field_value(id, v.clone());\n    Ok(None)\n}\n\nfn jvm_setErr0(env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let v = args.get(0).unwrap();\n    let cls = env.read().unwrap().class.clone();\n    let cls = cls.get_mut_class();\n    let id = cls.get_field_id(&util::S_ERR, &util::S_JAVA_IO_PRINT_STREAM, true);\n    cls.put_static_field_value(id, v.clone());\n    Ok(None)\n}\n\nfn jvm_mapLibraryName(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let v = args.get(0).unwrap();\n    let s = OopPtr::java_lang_string(v.extract_ref());\n\n    trace!(\"mapLibraryName libname = {}\", s);\n    let mut name = String::new();\n    if cfg!(target_os = \"macos\") {\n        name.push_str(\"lib\");\n        name.push_str(&s);\n        name.push_str(\".dylib\");\n    } else if cfg!(target_os = \"windows\") {\n        unimplemented!();\n    //        name.extend_from_slice(s.as_bytes());\n    //        name.extend_from_slice(\".dll\".as_bytes());\n    } else if cfg!(target_os = \"linux\") {\n        unimplemented!();\n    //        name.extend_from_slice(\"lib\".as_bytes());\n    //        name.extend_from_slice(s.as_bytes());\n    //        name.extend_from_slice(\".so\".as_bytes());\n    } else {\n        unimplemented!()\n    }\n    trace!(\"mapLibraryName name = {}\", name);\n\n    let v = util::oop::new_java_lang_string2(&name);\n\n    Ok(Some(v))\n}\n\nfn jvm_loadLibrary(_env: JNIEnv, _args: &[Oop]) -> JNIResult {\n    Ok(None)\n}\n\nfn jvm_identityHashCode(env: JNIEnv, args: &[Oop]) -> JNIResult {\n    native::java_lang_Object::jvm_hashCode(env, args)\n}\n\n/*\nfn jvm_getProperty(jt: &mut JavaThread, env: JNIEnv, args: Vec<OopRef>) -> JNIResult {\n    let key = args.get(0).unwrap();\n\n    let str_key = util::oop::extract_str(key.clone());\n    warn!(\"xxxx jvm_getProperty key = {}\", str_key);\n\n    let cls = require_class3(None, b\"java/lang/System\").unwrap();\n    let props = {\n        let cls = cls.lock().unwrap();\n        let id = cls.get_field_id(b\"props\", b\"Ljava/util/Properties;\", true);\n        cls.get_static_field_value(id)\n    };\n\n    let prop_cls = require_class3(None, b\"java/util/Properties\").unwrap();\n    let mir = {\n        let cls = prop_cls.lock().unwrap();\n        let id = util::new_method_id(b\"getProperty\", b\"(Ljava/lang/String;)Ljava/lang/String;\");\n        cls.get_class_method(id).unwrap()\n    };\n\n    let args = vec![props, key.clone()];\n    let mut stack = Stack::new(1);\n    let mut jc = runtime::java_call::JavaCall::new_with_args(jt, mir, args);\n    jc.invoke(jt, &mut stack, false);\n\n    let v = stack.pop_ref();\n\n    //    trace!(\"xxxxx 1, str_key = {}\", String::from_utf8_lossy(str_key.as_slice()));\n    //    let str_v = util::oop::extract_str(v.clone());\n    //    warn!(\"xxxx jvm_getProperty v = {}\", String::from_utf8_lossy(str_v.as_slice()));\n    //    trace!(\"xxxxx 2\");\n\n    Ok(Some(v))\n}\n*/\n\nfn arraycopy_same_obj(buf: Arc<OopPtr>, src_pos: usize, dest_pos: usize, length: usize) {\n    let is_type_ary = {\n        let ptr = buf.get_raw_ptr();\n        unsafe {\n            match &(*ptr).v {\n                oop::RefKind::TypeArray(_) => true,\n                oop::RefKind::Array(_) => false,\n                _ => unreachable!(),\n            }\n        }\n    };\n\n    if is_type_ary {\n        let ptr = buf.get_mut_raw_ptr();\n        unsafe {\n            match &mut (*ptr).v {\n                oop::RefKind::TypeArray(ary) => match ary {\n                    oop::TypeArrayDesc::Char(ary) => {\n                        ary.copy_within(src_pos..(src_pos + length), dest_pos)\n                    }\n                    oop::TypeArrayDesc::Byte(ary) => {\n                        ary.copy_within(src_pos..(src_pos + length), dest_pos)\n                    }\n                    t => unreachable!(\"t = {:?}\", t),\n                },\n\n                _ => unreachable!(),\n            }\n        }\n    } else {\n        let tmp = {\n            let ary = buf.extract_array();\n            let mut tmp = vec![Oop::Null; length];\n\n            let (_, ary) = ary.elements.split_at(src_pos);\n            tmp.clone_from_slice(&ary[..length]);\n            tmp\n        };\n\n        let ary = buf.extract_mut_array();\n        let (_, ary) = ary.elements.split_at_mut(dest_pos);\n        ary[..length].clone_from_slice(&tmp[..]);\n    }\n}\n\npub fn arraycopy_diff_obj(\n    src: Arc<OopPtr>,\n    src_pos: usize,\n    dest: Arc<OopPtr>,\n    dest_pos: usize,\n    length: usize,\n) {\n    let is_type_ary = {\n        let ptr = src.get_raw_ptr();\n        unsafe {\n            match &(*ptr).v {\n                oop::RefKind::TypeArray(_) => true,\n                oop::RefKind::Array(_) => false,\n                _ => unreachable!(),\n            }\n        }\n    };\n\n    // error!(\"src={}, dest={}, length={}, is_type_ary={}\", src_pos, dest_pos, length, is_type_ary);\n\n    let src_ptr = src.get_raw_ptr();\n\n    if is_type_ary {\n        unsafe {\n            match &(*src_ptr).v {\n                oop::RefKind::TypeArray(src_ary) => match src_ary {\n                    oop::TypeArrayDesc::Byte(src_ary) => {\n                        let dest_ary = dest.extract_mut_type_array();\n                        let dest_ary = dest_ary.extract_mut_bytes();\n                        let (_, dest_ptr) = dest_ary.split_at_mut(dest_pos);\n                        let (_, src_ptr) = src_ary.split_at(src_pos);\n                        dest_ptr[..length].copy_from_slice(&src_ptr[..length]);\n                    }\n                    oop::TypeArrayDesc::Char(src_ary) => {\n                        let dest_ary = dest.extract_mut_type_array();\n                        let dest_ary = dest_ary.extract_mut_chars();\n                        let (_, dest_ptr) = dest_ary.split_at_mut(dest_pos);\n                        let (_, src_ptr) = src_ary.split_at(src_pos);\n                        dest_ptr[..length].copy_from_slice(&src_ptr[..length]);\n                    }\n                    oop::TypeArrayDesc::Int(src_ary) => {\n                        let dest_ary = dest.extract_mut_type_array();\n                        let dest_ary = dest_ary.extract_mut_ints();\n                        let (_, dest_ptr) = dest_ary.split_at_mut(dest_pos);\n                        let (_, src_ptr) = src_ary.split_at(src_pos);\n                        dest_ptr[..length].copy_from_slice(&src_ptr[..length]);\n                    }\n                    t => unreachable!(\"t = {:?}\", t),\n                },\n                _ => unreachable!(),\n            }\n        }\n    } else {\n        let src = src.extract_array();\n        let dest = dest.extract_mut_array();\n\n        let (_, src_ptr) = src.elements.split_at(src_pos);\n        let (_, dest_ptr) = dest.elements.split_at_mut(dest_pos);\n\n        dest_ptr[..length].clone_from_slice(&src_ptr[..length]);\n    }\n}\n\nfn jvm_nanoTime(_env: JNIEnv, _args: &[Oop]) -> JNIResult {\n    let v = match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) {\n        Ok(n) => n.as_nanos(),\n        Err(_) => panic!(\"SystemTime before UNIX EPOCH!\"),\n    };\n    // let v = chrono::Utc::now().timestamp_nanos();\n    Ok(Some(Oop::new_long(v as i64)))\n}\n\nfn jvm_currentTimeMillis(_env: JNIEnv, _args: &[Oop]) -> JNIResult {\n    let v = match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) {\n        Ok(n) => n.as_millis(),\n        Err(_) => panic!(\"SystemTime before UNIX EPOCH!\"),\n    };\n\n    Ok(Some(Oop::new_long(v as i64)))\n}\n"
  },
  {
    "path": "crates/vm/src/native/java_lang_Thread.rs",
    "content": "#![allow(non_snake_case)]\n\nuse crate::native::{new_fn, JNIEnv, JNINativeMethod, JNIResult};\nuse crate::new_br;\nuse crate::oop::{Class, Oop, OopPtr};\nuse crate::runtime::vm::get_vm;\nuse crate::runtime::{self, vm, JavaCall, JavaThread};\n\npub fn get_native_methods() -> Vec<JNINativeMethod> {\n    vec![\n        new_fn(\"registerNatives\", \"()V\", Box::new(jvm_registerNatives)),\n        new_fn(\n            \"currentThread\",\n            \"()Ljava/lang/Thread;\",\n            Box::new(jvm_currentThread),\n        ),\n        new_fn(\"setPriority0\", \"(I)V\", Box::new(jvm_setPriority0)),\n        new_fn(\"isAlive\", \"()Z\", Box::new(jvm_isAlive)),\n        new_fn(\"start0\", \"()V\", Box::new(jvm_start0)),\n        new_fn(\"isInterrupted\", \"(Z)Z\", Box::new(jvm_isInterrupted)),\n    ]\n}\n\nfn jvm_registerNatives(_env: JNIEnv, _args: &[Oop]) -> JNIResult {\n    Ok(None)\n}\n\nfn jvm_currentThread(_env: JNIEnv, _args: &[Oop]) -> JNIResult {\n    let jt = runtime::thread::current_java_thread();\n    let obj = jt.read().unwrap().java_thread_obj.clone();\n    Ok(obj)\n}\n\nfn jvm_setPriority0(_env: JNIEnv, _args: &[Oop]) -> JNIResult {\n    Ok(None)\n}\n\n//'_jt' is caller's thread context, can't be used here\n//should find by 'eetop' in thread pool\nfn jvm_isAlive(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let this = args.get(0).unwrap();\n    let eetop = OopPtr::java_lang_thread_eetop(this.extract_ref());\n    let vm = get_vm();\n\n    let r = match vm.threads.find_java_thread(eetop) {\n        Some(jt) => {\n            info!(\"native thread tag = {}\", jt.read().unwrap().tag);\n            if jt.read().unwrap().is_alive {\n                1\n            } else {\n                0\n            }\n        }\n        None => 0,\n    };\n\n    Ok(Some(Oop::new_int(r)))\n}\n\nfn jvm_start0(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let thread_oop = args.get(0).unwrap().clone();\n    let clazz = {\n        let rf = thread_oop.extract_ref();\n        let inst = rf.extract_inst();\n        inst.class.clone()\n    };\n\n    let cls = clazz.get_class();\n    if cls.name.as_slice() == \"java/lang/ref/Reference$ReferenceHandler\".as_bytes() {\n        Ok(None)\n    } else {\n        let vm = vm::get_vm();\n\n        let jt = JavaThread::new(None, vm.threads.next_id());\n        vm.threads.attach_java_thread(jt.clone());\n\n        let args = vec![thread_oop.clone()];\n        vm.threads.spawn_java_thread(move || {\n            //setup current thread\n            let current_thread = jt.clone();\n            runtime::thread::THREAD.with(|t| {\n                *t.borrow_mut() = current_thread;\n            });\n\n            let cls = clazz.get_class();\n            let mir = {\n                //setup eetop\n                let eetop = jt.read().unwrap().eetop;\n                let fid = cls.get_field_id(&new_br(\"eetop\"), &new_br(\"J\"), false);\n                Class::put_field_value(thread_oop.extract_ref(), fid, Oop::new_long(eetop));\n\n                //obtain 'run' method\n                cls.get_virtual_method(&new_br(\"run\"), &new_br(\"()V\"))\n                    .unwrap()\n            };\n\n            //invoke 'run'\n            let mut jc = JavaCall::new_with_args(mir, args);\n            jt.write().unwrap().is_alive = true;\n            jt.write().unwrap().java_thread_obj = Some(thread_oop.clone());\n            jc.invoke(None, false);\n            jt.write().unwrap().is_alive = false;\n\n            //notify thread that invoke 'join'\n            let v = thread_oop.extract_ref();\n            v.notify_all();\n\n            vm.threads.detach_current_thread();\n        });\n\n        Ok(None)\n    }\n}\n\nfn jvm_isInterrupted(_env: JNIEnv, _args: &[Oop]) -> JNIResult {\n    //todo: fix me\n    let v = Oop::new_int(0);\n    Ok(Some(v))\n}\n"
  },
  {
    "path": "crates/vm/src/native/java_lang_Throwable.rs",
    "content": "#![allow(non_snake_case)]\n\nuse crate::native::{new_fn, JNIEnv, JNINativeMethod, JNIResult};\nuse crate::oop::{self, Class, Oop};\nuse crate::runtime::{self, require_class3};\nuse crate::{new_br, util};\nuse std::sync::atomic::Ordering;\n\npub fn get_native_methods() -> Vec<JNINativeMethod> {\n    vec![\n        new_fn(\n            \"fillInStackTrace\",\n            \"(I)Ljava/lang/Throwable;\",\n            Box::new(jvm_fillInStackTrace),\n        ),\n        new_fn(\n            \"getStackTraceDepth\",\n            \"()I\",\n            Box::new(jvm_getStackTraceDepth),\n        ),\n        new_fn(\n            \"getStackTraceElement\",\n            \"(I)Ljava/lang/StackTraceElement;\",\n            Box::new(jvm_getStackTraceElement),\n        ),\n    ]\n}\n\nfn jvm_fillInStackTrace(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let jt = runtime::thread::current_java_thread();\n\n    let elm_cls = oop::class::load_and_init(b\"java/lang/StackTraceElement\");\n    let ary_cls = require_class3(None, b\"[Ljava/lang/StackTraceElement;\").unwrap();\n\n    let throwable_oop = args.get(0).unwrap();\n    let mut backtrace = Vec::with_capacity(jt.read().unwrap().frames.len());\n\n    let mut found_ex_here = false;\n    let jth = jt.read().unwrap();\n    for it in jth.frames.iter() {\n        let ex_here = {\n            let it = it.try_read().unwrap();\n            it.ex_here.load(Ordering::Relaxed)\n        };\n\n        backtrace.push(it.clone());\n\n        if ex_here {\n            found_ex_here = true;\n            break;\n        }\n    }\n    drop(jth);\n\n    /*\n       todo: how handle throw better?\n\n    if no ex_here found, it's:\n      throw new AnnotationFormatError(\"Unexpected end of annotations.\");\n\n    new Throwable\n      Throwable.fillInStackTrace invoked, and come here\n\n    there are stacktraces for build 'Throwable' obj, not necessary for user, need discard\n\n    Exception in thread \"main\" java.lang.annotation.AnnotationFormatError: Unexpected end of annotations.\n       at java.lang.Throwable.fillInStackTrace(Throwable.java)\n       at java.lang.Throwable.fillInStackTrace(Throwable.java:783)\n       at java.lang.Throwable.<init>(Throwable.java:265)\n       at java.lang.Error.<init>(Error.java:70)\n       */\n    if !found_ex_here {\n        backtrace.pop();\n        backtrace.pop();\n        backtrace.pop();\n        backtrace.pop();\n    }\n\n    let mut traces = Vec::new();\n    for caller in backtrace.iter().rev() {\n        let (mir, pc) = {\n            let caller = caller.try_read().unwrap();\n            let pc = caller.pc.load(Ordering::Relaxed);\n            (caller.mir.clone(), pc)\n        };\n\n        let cls = mir.method.class.get_class();\n        let cls_name = unsafe { std::str::from_utf8_unchecked(cls.name.as_slice()) };\n        let cls_name = cls_name.replace(\"/\", \".\");\n        let method_name = unsafe { std::str::from_utf8_unchecked(mir.method.name.as_slice()) };\n        let src_file = {\n            let cls = mir.method.class.get_class();\n            cls.get_source_file()\n        };\n        let src_file = match src_file {\n            Some(name) => {\n                let name = unsafe { std::str::from_utf8_unchecked(name.as_slice()) };\n                util::oop::new_java_lang_string2(name)\n            }\n            None => util::oop::new_java_lang_string2(\"\"),\n        };\n        let line_num = mir.method.get_line_num((pc - 1) as u16);\n\n        let elm = Oop::new_inst(elm_cls.clone());\n        let args = vec![\n            elm.clone(),\n            util::oop::new_java_lang_string2(&cls_name),\n            util::oop::new_java_lang_string2(method_name),\n            src_file,\n            Oop::new_int(line_num),\n        ];\n        runtime::invoke::invoke_ctor(\n            elm_cls.clone(),\n            new_br(\"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V\"),\n            args,\n        );\n\n        traces.push(elm);\n    }\n\n    let stack_trace_ary = Oop::new_ref_ary2(ary_cls, traces);\n    let throwable_cls = require_class3(None, b\"java/lang/Throwable\").unwrap();\n    {\n        let cls = throwable_cls.get_class();\n        let id = cls.get_field_id(\n            &new_br(\"stackTrace\"),\n            &new_br(\"[Ljava/lang/StackTraceElement;\"),\n            false,\n        );\n        Class::put_field_value(throwable_oop.extract_ref(), id, Oop::Null);\n        let id = cls.get_field_id(&new_br(\"backtrace\"), &new_br(\"Ljava/lang/Object;\"), false);\n        Class::put_field_value(throwable_oop.extract_ref(), id, stack_trace_ary);\n    }\n\n    Ok(Some(throwable_oop.clone()))\n}\n\nfn jvm_getStackTraceDepth(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let throwable = args.get(0).unwrap();\n    let cls = {\n        let rf = throwable.extract_ref();\n        let inst = rf.extract_inst();\n        inst.class.clone()\n    };\n    let backtrace = {\n        let cls = cls.get_class();\n        let id = cls.get_field_id(&new_br(\"backtrace\"), &new_br(\"Ljava/lang/Object;\"), false);\n        Class::get_field_value(throwable.extract_ref(), id)\n    };\n\n    let v = match backtrace {\n        Oop::Null => Oop::new_int(0),\n        Oop::Ref(rf) => {\n            let ary = rf.extract_array();\n            let len = ary.elements.len();\n            Oop::new_int(len as i32)\n        }\n        _ => unreachable!(),\n    };\n\n    Ok(Some(v))\n}\n\nfn jvm_getStackTraceElement(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let throwable = args.get(0).unwrap();\n    let index = args.get(1).unwrap().extract_int();\n    let cls = {\n        let rf = throwable.extract_ref();\n        let inst = rf.extract_inst();\n        inst.class.clone()\n    };\n    let backtrace = {\n        let cls = cls.get_class();\n        let id = cls.get_field_id(&new_br(\"backtrace\"), &new_br(\"Ljava/lang/Object;\"), false);\n        Class::get_field_value(throwable.extract_ref(), id)\n    };\n\n    let v = {\n        let rf = backtrace.extract_ref();\n        let ary = rf.extract_array();\n        if index >= 0 && (index as usize) < ary.elements.len() {\n            ary.elements[index as usize].clone()\n        } else {\n            Oop::Null\n        }\n    };\n\n    Ok(Some(v))\n}\n"
  },
  {
    "path": "crates/vm/src/native/java_lang_reflect_Array.rs",
    "content": "#![allow(non_snake_case)]\n\nuse crate::native::{new_fn, JNIEnv, JNINativeMethod, JNIResult};\nuse crate::oop::{self, Oop, ValueType};\nuse crate::runtime::require_class3;\nuse crate::types::ClassRef;\n\npub fn get_native_methods() -> Vec<JNINativeMethod> {\n    vec![\n        new_fn(\n            \"newArray\",\n            \"(Ljava/lang/Class;I)Ljava/lang/Object;\",\n            Box::new(jvm_newArray),\n        ),\n        new_fn(\n            \"getLength\",\n            \"(Ljava/lang/Object;)I\",\n            Box::new(jvm_getLength),\n        ),\n    ]\n}\n\nfn jvm_newArray(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let mirror = args.get(0).unwrap();\n    //todo: throw NegativeArraySizeException\n    let length = args.get(1).unwrap().extract_int();\n\n    let (vt, component_cls) = {\n        let rf = mirror.extract_ref();\n        let mirror = rf.extract_mirror();\n        (mirror.value_type, mirror.target.clone())\n    };\n    let name = build_ary_name(vt, component_cls);\n    let ary_cls = require_class3(None, name.as_slice()).unwrap();\n    let v = Oop::new_ref_ary(ary_cls, length as usize);\n\n    Ok(Some(v))\n}\n\nfn jvm_getLength(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let ary = args.get(0).unwrap();\n    let rf = ary.extract_ref();\n    let ptr = rf.get_raw_ptr();\n    let len = unsafe {\n        match &(*ptr).v {\n            oop::RefKind::TypeArray(ary) => ary.len(),\n            oop::RefKind::Array(ary) => ary.elements.len(),\n            _ => unreachable!(),\n        }\n    };\n\n    let v = Oop::new_int(len as i32);\n    Ok(Some(v))\n}\n\nfn build_ary_name(vt: ValueType, component_cls: Option<ClassRef>) -> Vec<u8> {\n    let mut name = Vec::from(\"[\");\n\n    match vt {\n        ValueType::BYTE\n        | ValueType::BOOLEAN\n        | ValueType::CHAR\n        | ValueType::SHORT\n        | ValueType::INT\n        | ValueType::LONG\n        | ValueType::FLOAT\n        | ValueType::DOUBLE => name.extend_from_slice(vt.into()),\n        ValueType::OBJECT | ValueType::ARRAY => {\n            let cls = component_cls.unwrap();\n            let cls = cls.get_class();\n            match cls.get_class_kind_type() {\n                oop::class::ClassKindType::Instance => {\n                    name.extend_from_slice(b\"L\");\n                    name.extend_from_slice(cls.name.as_slice());\n                    name.extend_from_slice(b\";\");\n                }\n                oop::class::ClassKindType::ObjectAry => {\n                    name.extend_from_slice(cls.name.as_slice());\n                    name.extend_from_slice(b\";\");\n                }\n                oop::class::ClassKindType::TypAry => unimplemented!(),\n            }\n        }\n\n        ValueType::VOID => unreachable!(),\n    }\n\n    name\n}\n"
  },
  {
    "path": "crates/vm/src/native/java_lang_reflect_Proxy.rs",
    "content": "#![allow(non_snake_case)]\n\nuse crate::native;\nuse crate::native::{new_fn, JNIEnv, JNINativeMethod, JNIResult};\nuse crate::oop::class::ClassPtr;\nuse crate::oop::{self, Class, Oop, OopPtr};\nuse crate::runtime;\nuse crate::types::ClassRef;\nuse class_parser::parse_class;\nuse std::sync::Arc;\n\npub fn get_native_methods() -> Vec<JNINativeMethod> {\n    vec![new_fn(\n        \"defineClass0\",\n        \"(Ljava/lang/ClassLoader;Ljava/lang/String;[BII)Ljava/lang/Class;\",\n        Box::new(jvm_defineClass0),\n    )]\n}\n\nfn jvm_defineClass0(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let _loader = args.get(0).unwrap();\n    let name = args.get(1).unwrap();\n    let name = OopPtr::java_lang_string(name.extract_ref());\n    let b = args.get(2).unwrap();\n    let off = args.get(3).unwrap().extract_int();\n    let len = args.get(4).unwrap().extract_int();\n\n    let name = name.replace(\".\", \"/\");\n\n    //parse bytes => class, put in sys_dic\n    let class = do_parse_class(b, off as usize, len as usize);\n    runtime::sys_dic_put(name.as_bytes(), class.clone());\n    {\n        let this_ref = class.clone();\n        let cls = class.get_mut_class();\n        cls.set_class_state(oop::class::State::Loaded);\n        cls.link_class(this_ref);\n    }\n    native::java_lang_Class::create_mirror(class.clone());\n\n    let v = Oop::new_mirror(class);\n    Ok(Some(v))\n}\n\nfn do_parse_class(v: &Oop, off: usize, len: usize) -> ClassRef {\n    let rf = v.extract_ref();\n    let ary = rf.extract_type_array();\n    let ary = ary.extract_bytes();\n    match parse_class(&ary[off..(off + len)]) {\n        Ok(r) => {\n            let cfr = Arc::new(Box::new(r.1));\n            //fixme: setup classloader\n            let class = Class::new_class(cfr, None);\n            ClassPtr::new(class)\n        }\n        Err(e) => unreachable!(\"e = {:?}\", e),\n    }\n}\n"
  },
  {
    "path": "crates/vm/src/native/java_security_AccessController.rs",
    "content": "#![allow(non_snake_case)]\nuse crate::native::{new_fn, JNIEnv, JNINativeMethod, JNIResult};\nuse crate::oop::{self, Oop};\nuse crate::runtime::{self, exception, thread, JavaCall};\nuse crate::util;\nuse classfile::consts as cls_consts;\n\npub fn get_native_methods() -> Vec<JNINativeMethod> {\n    vec![\n        new_fn(\n            \"doPrivileged\",\n            \"(Ljava/security/PrivilegedAction;)Ljava/lang/Object;\",\n            Box::new(jvm_doPrivileged),\n        ),\n        new_fn(\n            \"doPrivileged\",\n            \"(Ljava/security/PrivilegedExceptionAction;)Ljava/lang/Object;\",\n            Box::new(jvm_doPrivileged2),\n        ),\n        new_fn(\n            \"getStackAccessControlContext\",\n            \"()Ljava/security/AccessControlContext;\",\n            Box::new(jvm_getStackAccessControlContext),\n        ),\n        new_fn(\"doPrivileged\", \"(Ljava/security/PrivilegedExceptionAction;Ljava/security/AccessControlContext;)Ljava/lang/Object;\", Box::new(jvm_doPrivileged3)),\n    ]\n}\n\nfn jvm_doPrivileged(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let v = args.get(0).unwrap();\n\n    let mir = {\n        match v {\n            Oop::Null => {\n                let ex = exception::new(cls_consts::J_NPE, None);\n                return Err(ex);\n            }\n            Oop::Ref(v) => {\n                let inst = v.extract_inst();\n                let cls = inst.class.get_class();\n                cls.get_virtual_method(&util::S_RUN, &util::S_RUN_SIG)\n                    .unwrap()\n            }\n            _ => unreachable!(),\n        }\n    };\n\n    let args = vec![v.clone()];\n    let mut jc = JavaCall::new_with_args(mir, args);\n    let area = runtime::DataArea::new(1);\n    jc.invoke(Some(&area), false);\n\n    if !thread::is_meet_ex() {\n        let mut stack = area.stack.borrow_mut();\n        let r = stack.pop_ref();\n        Ok(Some(r))\n    } else {\n        Ok(None)\n    }\n}\n\n//todo: re impl\nfn jvm_doPrivileged2(env: JNIEnv, args: &[Oop]) -> JNIResult {\n    jvm_doPrivileged(env, args)\n}\n\n//todo: re impl\nfn jvm_doPrivileged3(env: JNIEnv, args: &[Oop]) -> JNIResult {\n    jvm_doPrivileged(env, args)\n}\n\nfn jvm_getStackAccessControlContext(_env: JNIEnv, _args: &[Oop]) -> JNIResult {\n    Ok(Some(Oop::Null))\n}\n"
  },
  {
    "path": "crates/vm/src/native/java_util_concurrent_atomic_AtomicLong.rs",
    "content": "#![allow(non_snake_case)]\n\nuse crate::native::{new_fn, JNIEnv, JNINativeMethod, JNIResult};\nuse crate::oop::Oop;\n\npub fn get_native_methods() -> Vec<JNINativeMethod> {\n    vec![new_fn(\"VMSupportsCS8\", \"()Z\", Box::new(jvm_VMSupportsCS8))]\n}\n\nfn jvm_VMSupportsCS8(_env: JNIEnv, _args: &[Oop]) -> JNIResult {\n    Ok(Some(Oop::new_int(0)))\n}\n"
  },
  {
    "path": "crates/vm/src/native/mod.rs",
    "content": "#![allow(non_snake_case)]\n\nuse crate::oop::Oop;\nuse crate::types::ClassRef;\nuse rustc_hash::FxHashMap;\nuse std::sync::{Arc, RwLock};\n\nmod common;\n\nmod java_io_FileDescriptor;\nmod java_io_FileInputStream;\nmod java_io_FileOutputStream;\nmod java_io_UnixFileSystem;\npub mod java_lang_Class;\nmod java_lang_ClassLoader;\nmod java_lang_Double;\nmod java_lang_Float;\nmod java_lang_Object;\nmod java_lang_Runtime;\nmod java_lang_String;\nmod java_lang_System;\nmod java_lang_Thread;\nmod java_lang_Throwable;\nmod java_lang_reflect_Array;\nmod java_lang_reflect_Proxy;\nmod java_security_AccessController;\nmod java_util_concurrent_atomic_AtomicLong;\nmod sun_misc_Signal;\nmod sun_misc_URLClassPath;\nmod sun_misc_Unsafe;\nmod sun_misc_VM;\nmod sun_nio_cs_StreamEncoder;\nmod sun_reflect_ConstantPool;\nmod sun_reflect_NativeConstructorAccessorImpl;\nmod sun_reflect_NativeMethodAccessorImpl;\nmod sun_reflect_Reflection;\n\npub type JNIEnv = Arc<RwLock<Box<JNIEnvStruct>>>;\npub type JNIResult = Result<Option<Oop>, Oop>;\npub type NativeMethodPtr = Box<dyn Fn(JNIEnv, &[Oop]) -> JNIResult + Send + Sync>;\npub type JNINativeMethod = Arc<JNINativeMethodStruct>;\n\npub struct JNINativeMethodStruct {\n    name: &'static str,\n    signature: &'static str,\n    fnptr: NativeMethodPtr,\n}\n\npub struct JNIEnvStruct {\n    pub class: ClassRef,\n}\n\nlazy_static! {\n    //(class name, method name, method signature) -> JNINativeMethod\n    static ref NATIVES: FxHashMap<(&'static str, &'static str, &'static str), JNINativeMethod> = {\n        create_native_fn_tables()\n    };\n}\n\npub fn new_fn(\n    name: &'static str,\n    signature: &'static str,\n    fnptr: NativeMethodPtr,\n) -> JNINativeMethod {\n    Arc::new(JNINativeMethodStruct {\n        name,\n        signature,\n        fnptr,\n    })\n}\n\npub fn new_jni_env(class: ClassRef) -> JNIEnv {\n    Arc::new(RwLock::new(Box::new(JNIEnvStruct { class })))\n}\n\npub fn find_symbol(package: &[u8], name: &[u8], desc: &[u8]) -> Option<JNINativeMethod> {\n    let package = unsafe { std::str::from_utf8_unchecked(package) };\n    let name = unsafe { std::str::from_utf8_unchecked(name) };\n    let desc = unsafe { std::str::from_utf8_unchecked(desc) };\n\n    let k = (package, name, desc);\n    NATIVES.get(&k).cloned()\n}\n\npub fn init() {\n    lazy_static::initialize(&NATIVES);\n    java_lang_Class::init();\n}\n\nimpl JNINativeMethodStruct {\n    pub fn invoke(&self, jni: JNIEnv, args: &[Oop]) -> JNIResult {\n        (self.fnptr)(jni, args)\n    }\n}\n\nfn create_native_fn_tables(\n) -> FxHashMap<(&'static str, &'static str, &'static str), JNINativeMethod> {\n    let mut dict = FxHashMap::default();\n    let natives = vec![\n        (\n            \"java/io/FileDescriptor\",\n            java_io_FileDescriptor::get_native_methods(),\n        ),\n        (\n            \"java/io/FileInputStream\",\n            java_io_FileInputStream::get_native_methods(),\n        ),\n        (\n            \"java/io/FileOutputStream\",\n            java_io_FileOutputStream::get_native_methods(),\n        ),\n        (\n            \"java/io/UnixFileSystem\",\n            java_io_UnixFileSystem::get_native_methods(),\n        ),\n        (\"java/lang/Class\", java_lang_Class::get_native_methods()),\n        (\n            \"java/lang/ClassLoader\",\n            java_lang_ClassLoader::get_native_methods(),\n        ),\n        (\"java/lang/Double\", java_lang_Double::get_native_methods()),\n        (\"java/lang/Float\", java_lang_Float::get_native_methods()),\n        (\"java/lang/Object\", java_lang_Object::get_native_methods()),\n        (\n            \"java/lang/reflect/Array\",\n            java_lang_reflect_Array::get_native_methods(),\n        ),\n        (\n            \"java/lang/reflect/Proxy\",\n            java_lang_reflect_Proxy::get_native_methods(),\n        ),\n        (\"java/lang/Runtime\", java_lang_Runtime::get_native_methods()),\n        (\"java/lang/String\", java_lang_String::get_native_methods()),\n        (\"java/lang/System\", java_lang_System::get_native_methods()),\n        (\"java/lang/Thread\", java_lang_Thread::get_native_methods()),\n        (\n            \"java/lang/Throwable\",\n            java_lang_Throwable::get_native_methods(),\n        ),\n        (\n            \"java/security/AccessController\",\n            java_security_AccessController::get_native_methods(),\n        ),\n        (\n            \"java/util/concurrent/atomic/AtomicLong\",\n            java_util_concurrent_atomic_AtomicLong::get_native_methods(),\n        ),\n        (\"sun/misc/Signal\", sun_misc_Signal::get_native_methods()),\n        (\"sun/misc/Unsafe\", sun_misc_Unsafe::get_native_methods()),\n        (\n            \"sun/misc/URLClassPath\",\n            sun_misc_URLClassPath::get_native_methods(),\n        ),\n        (\"sun/misc/VM\", sun_misc_VM::get_native_methods()),\n        (\n            \"sun/nio/cs/StreamEncoder\",\n            sun_nio_cs_StreamEncoder::get_native_methods(),\n        ),\n        (\n            \"sun/reflect/ConstantPool\",\n            sun_reflect_ConstantPool::get_native_methods(),\n        ),\n        (\n            \"sun/reflect/NativeConstructorAccessorImpl\",\n            sun_reflect_NativeConstructorAccessorImpl::get_native_methods(),\n        ),\n        (\n            \"sun/reflect/NativeMethodAccessorImpl\",\n            sun_reflect_NativeMethodAccessorImpl::get_native_methods(),\n        ),\n        (\n            \"sun/reflect/Reflection\",\n            sun_reflect_Reflection::get_native_methods(),\n        ),\n    ];\n\n    {\n        natives.iter().for_each(|(package, methods)| {\n            methods.iter().for_each(|it| {\n                let k = (*package, it.name, it.signature);\n                dict.insert(k, it.clone());\n            });\n        });\n    }\n\n    dict\n}\n"
  },
  {
    "path": "crates/vm/src/native/sun_misc_Signal.rs",
    "content": "#![allow(non_snake_case)]\n\nuse crate::native::{new_fn, JNIEnv, JNINativeMethod, JNIResult};\nuse crate::oop::Oop;\n\npub fn get_native_methods() -> Vec<JNINativeMethod> {\n    vec![\n        new_fn(\n            \"findSignal\",\n            \"(Ljava/lang/String;)I\",\n            Box::new(jvm_findSignal),\n        ),\n        new_fn(\"handle0\", \"(IJ)J\", Box::new(jvm_handle0)),\n    ]\n}\n\n//todo: impl me\nfn jvm_findSignal(_env: JNIEnv, _args: &[Oop]) -> JNIResult {\n    Ok(Some(Oop::new_int(1)))\n}\n\n//todo: impl me\nfn jvm_handle0(_env: JNIEnv, _args: &[Oop]) -> JNIResult {\n    Ok(Some(Oop::new_long(0)))\n}\n"
  },
  {
    "path": "crates/vm/src/native/sun_misc_URLClassPath.rs",
    "content": "#![allow(non_snake_case)]\n\nuse crate::native::{new_fn, JNIEnv, JNINativeMethod, JNIResult};\nuse crate::oop::{self, Oop};\n\npub fn get_native_methods() -> Vec<JNINativeMethod> {\n    vec![new_fn(\n        \"getLookupCacheURLs\",\n        \"(Ljava/lang/ClassLoader;)[Ljava/net/URL;\",\n        Box::new(jvm_getLookupCacheURLs),\n    )]\n}\n\nfn jvm_getLookupCacheURLs(_env: JNIEnv, _args: &[Oop]) -> JNIResult {\n    Ok(Some(Oop::Null))\n}\n"
  },
  {
    "path": "crates/vm/src/native/sun_misc_Unsafe.rs",
    "content": "#![allow(non_snake_case)]\n\nuse crate::native::{java_lang_System, new_fn, JNIEnv, JNINativeMethod, JNIResult};\nuse crate::oop;\nuse crate::oop::{Class, Oop, OopPtr};\nuse crate::runtime::require_class3;\nuse crate::util;\nuse classfile::flags::ACC_STATIC;\nuse std::os::raw::c_void;\nuse std::time::{Duration, SystemTime, UNIX_EPOCH};\n\npub fn get_native_methods() -> Vec<JNINativeMethod> {\n    vec![\n        new_fn(\"registerNatives\", \"()V\", Box::new(jvm_registerNatives)),\n        new_fn(\n            \"arrayBaseOffset\",\n            \"(Ljava/lang/Class;)I\",\n            Box::new(jvm_arrayBaseOffset),\n        ),\n        new_fn(\n            \"arrayIndexScale\",\n            \"(Ljava/lang/Class;)I\",\n            Box::new(jvm_arrayIndexScale),\n        ),\n        new_fn(\"addressSize\", \"()I\", Box::new(jvm_addressSize)),\n        new_fn(\n            \"objectFieldOffset\",\n            \"(Ljava/lang/reflect/Field;)J\",\n            Box::new(jvm_objectFieldOffset),\n        ),\n        new_fn(\n            \"compareAndSwapObject\",\n            \"(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z\",\n            Box::new(jvm_compareAndSwapObject),\n        ),\n        new_fn(\n            \"getIntVolatile\",\n            \"(Ljava/lang/Object;J)I\",\n            Box::new(jvm_getIntVolatile),\n        ),\n        new_fn(\n            \"compareAndSwapInt\",\n            \"(Ljava/lang/Object;JII)Z\",\n            Box::new(jvm_compareAndSwapInt),\n        ),\n        new_fn(\"allocateMemory\", \"(J)J\", Box::new(jvm_allocateMemory)),\n        new_fn(\"freeMemory\", \"(J)V\", Box::new(jvm_freeMemory)),\n        new_fn(\"putLong\", \"(JJ)V\", Box::new(jvm_putLong)),\n        new_fn(\"getByte\", \"(J)B\", Box::new(jvm_getByte)),\n        new_fn(\n            \"compareAndSwapLong\",\n            \"(Ljava/lang/Object;JJJ)Z\",\n            Box::new(jvm_compareAndSwapLong),\n        ),\n        new_fn(\n            \"getObjectVolatile\",\n            \"(Ljava/lang/Object;J)Ljava/lang/Object;\",\n            Box::new(jvm_getObjectVolatile),\n        ),\n        new_fn(\"pageSize\", \"()I\", Box::new(jvm_pageSize)),\n        new_fn(\n            \"getLongVolatile\",\n            \"(Ljava/lang/Object;J)J\",\n            Box::new(jvm_getLongVolatile),\n        ),\n        new_fn(\n            \"setMemory\",\n            \"(Ljava/lang/Object;JJB)V\",\n            Box::new(jvm_setMemory),\n        ),\n        new_fn(\"putChar\", \"(JC)V\", Box::new(jvm_putChar)),\n        new_fn(\n            \"copyMemory\",\n            \"(Ljava/lang/Object;JLjava/lang/Object;JJ)V\",\n            Box::new(jvm_copyMemory),\n        ),\n        new_fn(\"getChar\", \"(J)C\", Box::new(jvm_getChar)),\n        new_fn(\n            \"putObject\",\n            \"(Ljava/lang/Object;JLjava/lang/Object;)V\",\n            Box::new(jvm_putObject),\n        ),\n        new_fn(\n            \"ensureClassInitialized\",\n            \"(Ljava/lang/Class;)V\",\n            Box::new(jvm_ensureClassInitialized),\n        ),\n        new_fn(\n            \"staticFieldOffset\",\n            \"(Ljava/lang/reflect/Field;)J\",\n            Box::new(jvm_staticFieldOffset),\n        ),\n        new_fn(\n            \"staticFieldBase\",\n            \"(Ljava/lang/reflect/Field;)Ljava/lang/Object;\",\n            Box::new(jvm_staticFieldBase),\n        ),\n        new_fn(\"putByte\", \"(Ljava/lang/Object;JB)V\", Box::new(jvm_putByte)),\n        new_fn(\"getByte\", \"(Ljava/lang/Object;J)B\", Box::new(jvm_getByte2)),\n        new_fn(\"park\", \"(ZJ)V\", Box::new(jvm_park)),\n    ]\n}\n\nfn jvm_registerNatives(_env: JNIEnv, _args: &[Oop]) -> JNIResult {\n    Ok(None)\n}\n\nfn jvm_arrayBaseOffset(_env: JNIEnv, _args: &[Oop]) -> JNIResult {\n    Ok(Some(Oop::new_int(0)))\n}\n\nfn jvm_arrayIndexScale(_env: JNIEnv, _args: &[Oop]) -> JNIResult {\n    Ok(Some(Oop::new_int(1)))\n}\n\nfn jvm_addressSize(_env: JNIEnv, _args: &[Oop]) -> JNIResult {\n    let v = std::mem::size_of::<*mut u8>();\n    Ok(Some(Oop::new_int(v as i32)))\n}\n\nfn jvm_objectFieldOffset(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let field = args.get(1).unwrap();\n    objectFieldOffset(field, false)\n}\n\n// fixme: The semantic requirement here is atomic operation, which needs to be re-implemented here\nfn jvm_compareAndSwapObject(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let owner = args.get(1).unwrap();\n    let offset = args.get(2).unwrap().extract_long();\n    let old_data = args.get(3).unwrap();\n    let new_data = args.get(4).unwrap();\n\n    let v_at_offset = Class::get_field_value2(owner.extract_ref(), offset as usize);\n\n    if OopPtr::is_eq(&v_at_offset, old_data) {\n        Class::put_field_value2(owner.extract_ref(), offset as usize, new_data.clone());\n        Ok(Some(Oop::new_int(1)))\n    } else {\n        Ok(Some(Oop::new_int(0)))\n    }\n}\n\nfn jvm_getIntVolatile(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let owner = args.get(1).unwrap();\n    let offset = args.get(2).unwrap().extract_long();\n    let v = Class::get_field_value2(owner.extract_ref(), offset as usize);\n    Ok(Some(v))\n}\n\nfn jvm_compareAndSwapInt(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let owner = args.get(1).unwrap();\n    let offset = args.get(2).unwrap().extract_long();\n    let old_data = args.get(3).unwrap().extract_int();\n    let new_data = args.get(4).unwrap();\n\n    let v_at_offset = {\n        let v = Class::get_field_value2(owner.extract_ref(), offset as usize);\n        v.extract_int()\n    };\n\n    if v_at_offset == old_data {\n        Class::put_field_value2(owner.extract_ref(), offset as usize, new_data.clone());\n        Ok(Some(Oop::new_int(1)))\n    } else {\n        Ok(Some(Oop::new_int(0)))\n    }\n}\n\nfn jvm_allocateMemory(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let size = args.get(1).unwrap().extract_long() as usize;\n    let arr = unsafe { libc::malloc(std::mem::size_of::<u8>() * size) };\n    let v = arr as i64;\n\n    Ok(Some(Oop::new_long(v)))\n}\n\nfn jvm_freeMemory(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let ptr = args.get(1).unwrap().extract_long() as *mut libc::c_void;\n\n    unsafe {\n        libc::free(ptr);\n    }\n\n    Ok(None)\n}\n\nfn jvm_putLong(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let ptr = args.get(1).unwrap().extract_long() as *mut libc::c_void;\n    let l = args.get(2).unwrap().extract_long();\n    let v = l.to_be_bytes();\n    unsafe {\n        libc::memcpy(ptr, v.as_ptr() as *const c_void, 8);\n    }\n\n    Ok(None)\n}\n\nfn jvm_getByte(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let ptr = args.get(1).unwrap().extract_long() as *const u8;\n    let v = unsafe { *ptr };\n    Ok(Some(Oop::new_int(v as i32)))\n}\n\nfn jvm_compareAndSwapLong(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let owner = args.get(1).unwrap();\n    let offset = args.get(2).unwrap().extract_long();\n    let old_data = args.get(3).unwrap().extract_long();\n    let new_data = args.get(4).unwrap();\n\n    let v_at_offset = {\n        let v = Class::get_field_value2(owner.extract_ref(), offset as usize);\n        v.extract_long()\n    };\n\n    if v_at_offset == old_data {\n        Class::put_field_value2(owner.extract_ref(), offset as usize, new_data.clone());\n        Ok(Some(Oop::new_int(1)))\n    } else {\n        Ok(Some(Oop::new_int(0)))\n    }\n}\n\nfn jvm_getObjectVolatile(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let owner = args.get(1).unwrap();\n    let offset = args.get(2).unwrap().extract_long();\n    let v_at_offset = Class::get_field_value2(owner.extract_ref(), offset as usize);\n    Ok(Some(v_at_offset))\n}\n\nfn jvm_pageSize(_env: JNIEnv, _args: &[Oop]) -> JNIResult {\n    Ok(Some(Oop::new_int(4 * 1024)))\n}\n\nfn jvm_getLongVolatile(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let owner = args.get(1).unwrap();\n    let offset = args.get(2).unwrap().extract_long();\n    let v_at_offset = Class::get_field_value2(owner.extract_ref(), offset as usize);\n    Ok(Some(v_at_offset))\n}\n\nfn jvm_setMemory(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let _this = args.get(0).unwrap();\n    let obj = args.get(1).unwrap();\n    let offset = args.get(2).unwrap().extract_long() as usize;\n    let size = args.get(3).unwrap().extract_long() as usize;\n    let value = args.get(4).unwrap().extract_int();\n\n    match obj {\n        Oop::Null => {\n            let dest = offset as *mut libc::c_void;\n            unsafe {\n                libc::memset(dest, value, size as usize);\n            }\n        }\n        Oop::Ref(rf) => {\n            let ary = rf.extract_mut_type_array();\n            let bytes = ary.extract_mut_bytes();\n            unsafe {\n                let addr = bytes.as_mut_ptr();\n                let addr = addr.add(offset);\n                std::ptr::write_bytes(addr, value as u8, size);\n            }\n        }\n        _ => unimplemented!(),\n    }\n\n    Ok(None)\n}\n\nfn jvm_putChar(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let dest = args.get(1).unwrap().extract_long() as *mut libc::c_void;\n    let value = args.get(2).unwrap().extract_int();\n\n    unsafe {\n        libc::memset(dest, value, 1);\n    }\n\n    Ok(None)\n}\n\nfn jvm_copyMemory(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let _this = args.get(0).unwrap();\n    let src_obj = args.get(1).unwrap();\n    let src_offset = args.get(2).unwrap().extract_long() as usize;\n    let dest_obj = args.get(3).unwrap();\n    let dest_offset = args.get(4).unwrap().extract_long() as usize;\n    let size = args.get(5).unwrap().extract_long() as usize;\n\n    match src_obj {\n        Oop::Null => {\n            match dest_obj {\n                //raw -> raw\n                Oop::Null => {\n                    let src_ptr = src_offset as *const u8;\n                    let dest_ptr = dest_offset as *mut u8;\n                    unsafe {\n                        std::ptr::copy(src_ptr, dest_ptr, size);\n                    }\n                }\n                //raw -> byte[]\n                Oop::Ref(dest) => {\n                    let dest = dest.extract_mut_type_array();\n                    let dest = dest.extract_mut_bytes();\n                    let dest = &mut dest[dest_offset..];\n                    let src_ptr = src_offset as *const u8;\n                    unsafe {\n                        for i in 0..size {\n                            let p = src_ptr.add(i);\n                            dest[i] = *p;\n                        }\n                    }\n                }\n                _ => unimplemented!(),\n            }\n        }\n        Oop::Ref(src) => {\n            match dest_obj {\n                //byte[] -> raw\n                Oop::Null => {\n                    let src = src.extract_type_array();\n                    let src = src.extract_bytes();\n                    let ptr = dest_offset as *mut u8;\n                    unsafe {\n                        for i in 0..size {\n                            let p = ptr.add(i);\n                            *p = src[src_offset + i];\n                        }\n                    }\n                }\n                //byte[] -> byte[]\n                Oop::Ref(dest) => {\n                    java_lang_System::arraycopy_diff_obj(\n                        src.clone(),\n                        src_offset,\n                        dest.clone(),\n                        dest_offset,\n                        size,\n                    );\n                }\n                _ => unimplemented!(),\n            }\n        }\n        _ => unreachable!(),\n    }\n\n    Ok(None)\n}\n\nfn jvm_getChar(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let arg1 = args.get(1).unwrap();\n    let ptr = arg1.extract_long() as *const u16;\n    let v = unsafe { *ptr };\n    Ok(Some(Oop::new_int(v as i32)))\n}\n\nfn jvm_putObject(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let _this = args.get(0).unwrap();\n    let o = args.get(1).unwrap();\n    let offset = args.get(2).unwrap().extract_long() as usize;\n    let x = args.get(3).unwrap();\n\n    let rf = o.extract_ref();\n    Class::put_field_value2(rf, offset, x.clone());\n    Ok(None)\n}\n\nfn jvm_ensureClassInitialized(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let clazz = args.get(1).unwrap();\n    let rf = clazz.extract_ref();\n    let mirror = rf.extract_mirror();\n    let target = mirror.target.clone().unwrap();\n    oop::class::init_class(&target);\n    oop::class::init_class_fully(&target);\n    Ok(None)\n}\n\nfn jvm_staticFieldOffset(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let field = args.get(1).unwrap();\n    objectFieldOffset(field, true)\n}\n\nfn jvm_staticFieldBase(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let field = args.get(1).unwrap();\n    let cls = require_class3(None, b\"java/lang/reflect/Field\").unwrap();\n    let cls = cls.get_class();\n    let id = cls.get_field_id(&util::S_CLAZZ, &util::S_JAVA_LANG_CLASS, false);\n    let v = Class::get_field_value(field.extract_ref(), id);\n    Ok(Some(v))\n}\n\nfn jvm_putByte(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let _this = args.get(0).unwrap();\n    let obj = args.get(1).unwrap();\n    let offset = args.get(2).unwrap().extract_long() as usize;\n    let x = args.get(3).unwrap().extract_int();\n\n    match obj {\n        Oop::Null => {\n            let dest = offset as *mut libc::c_void;\n            unsafe {\n                libc::memset(dest, x, 1);\n            }\n        }\n        Oop::Ref(rf) => {\n            let ary = rf.extract_mut_type_array();\n            let bytes = ary.extract_mut_bytes();\n            bytes[offset] = x as u8;\n        }\n        t => unimplemented!(\"{:?}\", t),\n    }\n\n    Ok(None)\n}\n\nfn jvm_getByte2(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let _this = args.get(0).unwrap();\n    let obj = args.get(1).unwrap();\n    let offset = args.get(2).unwrap().extract_long() as usize;\n\n    let v = match obj {\n        Oop::Null => {\n            let ptr = offset as *const u8;\n            let v = unsafe { *ptr };\n            Oop::new_int(v as i32)\n        }\n        Oop::Ref(rf) => {\n            let ary = rf.extract_mut_type_array();\n            let bytes = ary.extract_bytes();\n            let v = bytes[offset];\n            Oop::new_int(v as i32)\n        }\n        t => unimplemented!(\"{:?}\", t),\n    };\n\n    Ok(Some(v))\n}\n\nfn jvm_park(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let _this = args.get(0).unwrap();\n    let is_absolute = args.get(1).unwrap().extract_int() != 0;\n    let time = args.get(2).unwrap().extract_long() as u64;\n\n    if is_absolute {\n        let epoch_duration = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();\n        let diff = Duration::from_millis(time) - epoch_duration;\n        std::thread::park_timeout(diff);\n    } else {\n        if time != 0 {\n            std::thread::park_timeout(Duration::from_nanos(time));\n        } else {\n            std::thread::park();\n        }\n    }\n\n    Ok(None)\n}\n\n////////helper\n\nfn objectFieldOffset(field: &Oop, is_static: bool) -> JNIResult {\n    let cls = require_class3(None, b\"java/lang/reflect/Field\").unwrap();\n\n    if is_static {\n        let modifier = {\n            let cls = cls.get_class();\n            let id = cls.get_field_id(&util::S_MODIFIERS, &util::S_I, false);\n            let v = Class::get_field_value(field.extract_ref(), id);\n            v.extract_int() as u16\n        };\n        assert_eq!(modifier & ACC_STATIC, ACC_STATIC);\n    }\n\n    let slot = {\n        let cls = cls.get_class();\n        let id = cls.get_field_id(&util::S_SLOT, &util::S_I, false);\n        let v = Class::get_field_value(field.extract_ref(), id);\n        v.extract_int()\n    };\n\n    Ok(Some(Oop::new_long(slot as i64)))\n}\n"
  },
  {
    "path": "crates/vm/src/native/sun_misc_VM.rs",
    "content": "#![allow(non_snake_case)]\n\nuse crate::native::{new_fn, JNIEnv, JNINativeMethod, JNIResult};\nuse crate::oop::Oop;\n\npub fn get_native_methods() -> Vec<JNINativeMethod> {\n    vec![new_fn(\"initialize\", \"()V\", Box::new(jvm_initialize))]\n}\n\nfn jvm_initialize(_env: JNIEnv, _args: &[Oop]) -> JNIResult {\n    Ok(None)\n}\n"
  },
  {
    "path": "crates/vm/src/native/sun_nio_cs_StreamEncoder.rs",
    "content": "#![allow(non_snake_case)]\n\nuse crate::native::{new_fn, JNIEnv, JNINativeMethod, JNIResult};\nuse crate::new_br;\nuse crate::oop::Oop;\nuse crate::runtime::{self, require_class3};\n\npub fn get_native_methods() -> Vec<JNINativeMethod> {\n    vec![new_fn(\n        \"forOutputStreamWriter\",\n        \"(Ljava/io/OutputStream;Ljava/lang/Object;Ljava/lang/String;)Lsun/nio/cs/StreamEncoder;\",\n        Box::new(jvm_forOutputStreamWriter),\n    )]\n}\n\nfn jvm_forOutputStreamWriter(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let os = args.get(0).unwrap();\n    let obj = args.get(1).unwrap();\n    let _charset_name = args.get(2).unwrap();\n\n    let charset_cls = require_class3(None, b\"java/nio/charset/Charset\").unwrap();\n    let default_charset_oop = {\n        let cls = charset_cls.get_class();\n        let id = cls.get_field_id(\n            &new_br(\"defaultCharset\"),\n            &new_br(\"Ljava/nio/charset/Charset;\"),\n            true,\n        );\n        cls.get_static_field_value(id)\n    };\n\n    //check defaultCharset\n    match default_charset_oop {\n        Oop::Ref(_) => (),\n        _ => unreachable!(),\n    }\n\n    let encoder = require_class3(None, b\"sun/nio/cs/StreamEncoder\").unwrap();\n    let encoder_oop = Oop::new_inst(encoder.clone());\n    let args = vec![\n        encoder_oop.clone(),\n        os.clone(),\n        obj.clone(),\n        default_charset_oop,\n    ];\n\n    runtime::invoke::invoke_ctor(\n        encoder,\n        new_br(\"(Ljava/io/OutputStream;Ljava/lang/Object;Ljava/nio/charset/Charset;)V\"),\n        args,\n    );\n\n    Ok(Some(encoder_oop))\n}\n"
  },
  {
    "path": "crates/vm/src/native/sun_reflect_ConstantPool.rs",
    "content": "#![allow(non_snake_case)]\nuse crate::native::{new_fn, JNIEnv, JNINativeMethod, JNIResult};\nuse crate::oop::{self, Oop};\nuse crate::util;\nuse classfile::constant_pool;\n\npub fn get_native_methods() -> Vec<JNINativeMethod> {\n    vec![new_fn(\n        \"getUTF8At0\",\n        \"(Ljava/lang/Object;I)Ljava/lang/String;\",\n        Box::new(jvm_getUTF8At0),\n    )]\n}\n\nfn jvm_getUTF8At0(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let _this = args.get(0).unwrap();\n    let cp_oop = args.get(1).unwrap();\n    let index = {\n        let index = args.get(2).unwrap();\n        index.extract_int()\n    };\n\n    let rf = cp_oop.extract_ref();\n    let mirror = rf.extract_mirror();\n    let target = mirror.target.clone().unwrap();\n    let cls = target.get_class();\n    match &cls.kind {\n        oop::class::ClassKind::Instance(inst) => {\n            let cp = &inst.class_file.cp;\n            let s = constant_pool::get_utf8(cp, index as usize);\n            let s = unsafe { std::str::from_utf8_unchecked(s.as_slice()) };\n            let r = util::oop::new_java_lang_string2(s);\n            Ok(Some(r))\n        }\n        _ => unimplemented!(),\n    }\n}\n"
  },
  {
    "path": "crates/vm/src/native/sun_reflect_NativeConstructorAccessorImpl.rs",
    "content": "#![allow(non_snake_case)]\n\nuse crate::native::{common, new_fn, JNIEnv, JNINativeMethod, JNIResult};\nuse crate::oop::Oop;\nuse crate::{new_br, runtime};\n\npub fn get_native_methods() -> Vec<JNINativeMethod> {\n    vec![new_fn(\n        \"newInstance0\",\n        \"(Ljava/lang/reflect/Constructor;[Ljava/lang/Object;)Ljava/lang/Object;\",\n        Box::new(jvm_newInstance0),\n    )]\n}\n\nfn jvm_newInstance0(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let ctor = args.get(0).unwrap();\n    let arguments = args.get(1).unwrap();\n\n    let clazz = common::reflect::get_Constructor_clazz(ctor);\n    let target_cls = {\n        let rf = clazz.extract_ref();\n        let mirror = rf.extract_mirror();\n        mirror.target.clone().unwrap()\n    };\n\n    let signature = common::reflect::get_Constructor_signature(ctor);\n\n    let cls = target_cls.get_class();\n    let name = unsafe { std::str::from_utf8_unchecked(cls.name.as_slice()) };\n    info!(\"newInstance0 {}:{}\", name, signature);\n\n    let mut ctor_args = Vec::new();\n    {\n        match arguments {\n            Oop::Null => (),\n            Oop::Ref(rf) => {\n                let ary = rf.extract_array();\n                ctor_args.extend_from_slice(ary.elements.as_slice());\n            }\n            _ => unreachable!(),\n        }\n    }\n\n    let oop = Oop::new_inst(target_cls.clone());\n    ctor_args.insert(0, oop.clone());\n    runtime::invoke::invoke_ctor(target_cls, new_br(signature.as_str()), ctor_args);\n\n    Ok(Some(oop))\n}\n"
  },
  {
    "path": "crates/vm/src/native/sun_reflect_NativeMethodAccessorImpl.rs",
    "content": "#![allow(non_snake_case)]\n\nuse crate::native::{new_fn, JNIEnv, JNINativeMethod, JNIResult};\nuse crate::new_br;\nuse crate::oop::{self, Class, Oop, OopPtr};\nuse crate::runtime::{self, require_class3};\nuse crate::util;\nuse classfile::{consts as cls_consts, SignatureType};\n\npub fn get_native_methods() -> Vec<JNINativeMethod> {\n    vec![new_fn(\n        \"invoke0\",\n        \"(Ljava/lang/reflect/Method;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;\",\n        Box::new(jvm_invoke0),\n    )]\n}\n\nfn jvm_invoke0(_env: JNIEnv, args: &[Oop]) -> JNIResult {\n    let method = args.get(0).unwrap();\n    let obj = args.get(1).unwrap();\n    let args = args.get(2).unwrap();\n\n    let cls = require_class3(None, cls_consts::J_METHOD).unwrap();\n\n    let (m_clazz, m_name, m_signature) = {\n        let cls = cls.get_class();\n\n        let fid = cls.get_field_id(&util::S_CLAZZ, &util::S_JAVA_LANG_CLASS, false);\n        let method_clazz = Class::get_field_value(method.extract_ref(), fid);\n\n        let fid = cls.get_field_id(&util::S_NAME, &util::S_JAVA_LANG_STRING, false);\n        let method_name = Class::get_field_value(method.extract_ref(), fid);\n        let method_name = OopPtr::java_lang_string(method_name.extract_ref());\n        let method_name = new_br(method_name.as_str());\n\n        let fid = cls.get_field_id(&util::S_SIGNATURE, &util::S_JAVA_LANG_STRING, false);\n        let signature = Class::get_field_value(method.extract_ref(), fid);\n        let signature = OopPtr::java_lang_string(signature.extract_ref());\n        let signature = new_br(signature.as_str());\n\n        (method_clazz, method_name, signature)\n    };\n\n    let clz = {\n        let rf = m_clazz.extract_ref();\n        let mirror = rf.extract_mirror();\n        mirror.target.clone().unwrap()\n    };\n\n    let mir = {\n        let clz = clz.get_class();\n        clz.get_class_method(&m_name, &m_signature).unwrap()\n    };\n\n    // {\n    //     let cls = clz.read().unwrap();\n    //     let cls_name = cls.name.clone();\n    //     error!(\n    //         \"invoke0 {}:{}:{} static={}, native={}\",\n    //         String::from_utf8_lossy(cls_name.as_slice()),\n    //         String::from_utf8_lossy(mir.method.name.as_slice()),\n    //         String::from_utf8_lossy(mir.method.desc.as_slice()),\n    //         mir.method.is_static(),\n    //         mir.method.is_native(),\n    //     );\n    // }\n\n    let mut args = {\n        let rf = args.extract_ref();\n        let ary = rf.extract_array();\n        ary.elements.to_vec()\n    };\n\n    if !mir.method.is_static() {\n        args.insert(0, obj.clone());\n    }\n\n    let force_no_resolve = mir.method.name.as_slice() == b\"<init>\" || mir.method.is_static();\n    let mut jc = runtime::invoke::JavaCall::new_with_args(mir, args);\n    let area = runtime::DataArea::new(0);\n    jc.invoke(Some(&area), force_no_resolve);\n\n    let r = {\n        let mut stack = area.stack.borrow_mut();\n        match jc.mir.method.signature.retype {\n            SignatureType::Byte\n            | SignatureType::Char\n            | SignatureType::Boolean\n            | SignatureType::Short\n            | SignatureType::Int => {\n                let v = stack.pop_int();\n                Some(oop::Oop::new_int(v))\n            }\n            SignatureType::Double => {\n                let v = stack.pop_double();\n                Some(oop::Oop::new_double(v))\n            }\n            SignatureType::Float => {\n                let v = stack.pop_float();\n                Some(oop::Oop::new_float(v))\n            }\n            SignatureType::Long => {\n                let v = stack.pop_long();\n                Some(oop::Oop::new_long(v))\n            }\n            SignatureType::Object(_, _, _) | SignatureType::Array(_) => Some(stack.pop_ref()),\n            SignatureType::Void => Some(Oop::Null),\n        }\n    };\n\n    Ok(r)\n}\n"
  },
  {
    "path": "crates/vm/src/native/sun_reflect_Reflection.rs",
    "content": "#![allow(non_snake_case)]\n\nuse crate::native::{self, new_fn, JNIEnv, JNINativeMethod, JNIResult};\nuse crate::oop::Oop;\nuse crate::runtime;\n\npub fn get_native_methods() -> Vec<JNINativeMethod> {\n    vec![\n        new_fn(\n            \"getCallerClass\",\n            \"()Ljava/lang/Class;\",\n            Box::new(jvm_getCallerClass),\n        ),\n        new_fn(\n            \"getClassAccessFlags\",\n            \"(Ljava/lang/Class;)I\",\n            Box::new(jvm_getClassAccessFlags),\n        ),\n    ]\n}\n\nfn jvm_getCallerClass(_env: JNIEnv, _args: &[Oop]) -> JNIResult {\n    let jt = runtime::thread::current_java_thread();\n    let mut callers = { jt.read().unwrap().frames.clone() };\n\n    {\n        let cur = {\n            let cur = callers.pop().unwrap(); //pop cur method\n            let cur = cur.try_read().unwrap();\n            cur.mir.clone()\n        };\n        debug_assert_eq!(cur.method.name.as_slice(), b\"getCallerClass\");\n    }\n\n    loop {\n        let caller = {\n            let caller = callers.pop().unwrap();\n            let caller = caller.try_read().unwrap();\n            caller.mir.clone()\n        };\n        if caller\n            .method\n            .check_annotation(b\"Lsun/reflect/CallerSensitive;\")\n        {\n            continue;\n        }\n\n        let cls = caller.method.class.get_class();\n        //        error!(\"getCallerClass name = {}\", String::from_utf8_lossy(cls.name.as_slice()));\n        return Ok(Some(cls.get_mirror()));\n    }\n}\n\nfn jvm_getClassAccessFlags(env: JNIEnv, args: &[Oop]) -> JNIResult {\n    native::java_lang_Class::jvm_getModifiers(env, args)\n}\n"
  },
  {
    "path": "crates/vm/src/oop/ary.rs",
    "content": "use crate::oop::{class, Oop};\nuse crate::types::*;\n\n#[derive(Debug, Clone)]\npub struct ArrayOopDesc {\n    pub class: ClassRef,\n    pub elements: Vec<Oop>,\n}\n\n#[derive(Debug, Clone)]\npub enum TypeArrayDesc {\n    Byte(ByteAry),\n    Bool(BoolAry),\n    Char(CharAry),\n    Short(ShortAry),\n    Float(FloatAry),\n    Double(DoubleAry),\n    Int(IntAry),\n    Long(LongAry),\n}\n\npub enum TypeArrayEnum {\n    Boolean,\n    Char,\n    Float,\n    Double,\n    Byte,\n    Short,\n    Int,\n    Long,\n}\n\nimpl ArrayOopDesc {\n    pub fn new(class: ClassRef, elements: Vec<Oop>) -> Self {\n        {\n            debug_assert!(class.get_class().is_array());\n        }\n\n        Self { class, elements }\n    }\n\n    pub fn get_dimension(&self) -> usize {\n        let class = self.class.get_class();\n        match &class.kind {\n            class::ClassKind::ObjectArray(ary_class_obj) => ary_class_obj.get_dimension(),\n            class::ClassKind::TypeArray(ary_class_obj) => ary_class_obj.get_dimension(),\n            _ => unreachable!(),\n        }\n    }\n}\n\nimpl TypeArrayDesc {\n    pub fn len(&self) -> usize {\n        match self {\n            TypeArrayDesc::Char(ary) => ary.len(),\n            TypeArrayDesc::Byte(ary) => ary.len(),\n            TypeArrayDesc::Bool(ary) => ary.len(),\n            TypeArrayDesc::Short(ary) => ary.len(),\n            TypeArrayDesc::Float(ary) => ary.len(),\n            TypeArrayDesc::Double(ary) => ary.len(),\n            TypeArrayDesc::Int(ary) => ary.len(),\n            TypeArrayDesc::Long(ary) => ary.len(),\n        }\n    }\n}\n\nimpl TypeArrayDesc {\n    pub fn extract_chars(&self) -> &CharAry {\n        match self {\n            TypeArrayDesc::Char(v) => v,\n            _ => unreachable!(),\n        }\n    }\n\n    pub fn extract_mut_chars(&mut self) -> &mut CharAry {\n        match self {\n            TypeArrayDesc::Char(v) => v,\n            _ => unreachable!(),\n        }\n    }\n\n    pub fn extract_bytes(&self) -> &ByteAry {\n        match self {\n            TypeArrayDesc::Byte(v) => v,\n            _ => unreachable!(),\n        }\n    }\n\n    pub fn extract_mut_bytes(&mut self) -> &mut ByteAry {\n        match self {\n            TypeArrayDesc::Byte(v) => v,\n            _ => unreachable!(),\n        }\n    }\n\n    pub fn extract_bools(&self) -> &BoolAry {\n        match self {\n            TypeArrayDesc::Bool(v) => v,\n            _ => unreachable!(),\n        }\n    }\n\n    pub fn extract_mut_bools(&mut self) -> &mut BoolAry {\n        match self {\n            TypeArrayDesc::Bool(v) => v,\n            _ => unreachable!(),\n        }\n    }\n\n    pub fn extract_shorts(&self) -> &ShortAry {\n        match self {\n            TypeArrayDesc::Short(v) => v,\n            _ => unreachable!(),\n        }\n    }\n\n    pub fn extract_mut_shorts(&mut self) -> &mut ShortAry {\n        match self {\n            TypeArrayDesc::Short(v) => v,\n            _ => unreachable!(),\n        }\n    }\n\n    pub fn extract_floats(&self) -> &FloatAry {\n        match self {\n            TypeArrayDesc::Float(v) => v,\n            _ => unreachable!(),\n        }\n    }\n\n    pub fn extract_mut_floats(&mut self) -> &mut FloatAry {\n        match self {\n            TypeArrayDesc::Float(v) => v,\n            _ => unreachable!(),\n        }\n    }\n\n    pub fn extract_doubles(&self) -> &DoubleAry {\n        match self {\n            TypeArrayDesc::Double(v) => v,\n            _ => unreachable!(),\n        }\n    }\n\n    pub fn extract_mut_doubles(&mut self) -> &mut DoubleAry {\n        match self {\n            TypeArrayDesc::Double(v) => v,\n            _ => unreachable!(),\n        }\n    }\n\n    pub fn extract_ints(&self) -> &IntAry {\n        match self {\n            TypeArrayDesc::Int(v) => v,\n            _ => unreachable!(),\n        }\n    }\n\n    pub fn extract_mut_ints(&mut self) -> &mut IntAry {\n        match self {\n            TypeArrayDesc::Int(v) => v,\n            _ => unreachable!(),\n        }\n    }\n\n    pub fn extract_longs(&self) -> &LongAry {\n        match self {\n            TypeArrayDesc::Long(v) => v,\n            _ => unreachable!(),\n        }\n    }\n\n    pub fn extract_mut_longs(&mut self) -> &mut LongAry {\n        match self {\n            TypeArrayDesc::Long(v) => v,\n            _ => unreachable!(),\n        }\n    }\n}\n\nimpl From<u8> for TypeArrayEnum {\n    fn from(b: u8) -> Self {\n        match b {\n            4 => Self::Boolean,\n            5 => Self::Char,\n            6 => Self::Float,\n            7 => Self::Double,\n            8 => Self::Byte,\n            9 => Self::Short,\n            10 => Self::Int,\n            11 => Self::Long,\n            _ => unreachable!(),\n        }\n    }\n}\n"
  },
  {
    "path": "crates/vm/src/oop/class.rs",
    "content": "use std::fmt::{self, Debug, Error, Formatter};\nuse std::ops::{Deref, DerefMut};\nuse std::sync::atomic::Ordering;\nuse std::sync::{Arc, Mutex};\n\nuse rustc_hash::FxHashMap;\n\nuse classfile::{\n    attributes::EnclosingMethod, attributes::InnerClass, constant_pool,\n    constant_pool::get_utf8 as get_cp_utf8, consts, flags::*, AttributeType, BytesRef, U2,\n};\n\nuse crate::oop::{self, consts as oop_consts, field, Oop, OopPtr, RefKindDesc, ValueType};\nuse crate::runtime::method::MethodId;\nuse crate::runtime::thread::ReentrantMutex;\nuse crate::runtime::{\n    self, method, require_class2, ClassLoader, ConstantPoolCache, JavaCall, JavaThread,\n};\nuse crate::types::*;\nuse crate::{native, util};\n\npub struct ClassPtr(u64);\n\nimpl ClassPtr {\n    pub fn new(v: Class) -> ClassRef {\n        let v = Box::new(v);\n        let ptr = Box::into_raw(v) as u64;\n        Arc::new(ClassPtr(ptr))\n    }\n}\n\nimpl Drop for ClassPtr {\n    fn drop(&mut self) {\n        let _v = unsafe { Box::from_raw(self.0 as *mut Class) };\n    }\n}\n\nimpl ClassPtr {\n    fn raw_ptr(&self) -> *const Class {\n        self.0 as *const Class\n    }\n\n    fn raw_mut_ptr(&self) -> *mut Class {\n        self.0 as *mut Class\n    }\n}\n\nimpl ClassPtr {\n    pub fn name(&self) -> BytesRef {\n        let ptr = self.raw_ptr();\n        unsafe { (*ptr).name.clone() }\n    }\n\n    pub fn get_class(&self) -> &Class {\n        let ptr = self.raw_ptr();\n        unsafe { &(*ptr) }\n    }\n\n    pub fn get_mut_class(&self) -> &mut Class {\n        let ptr = self.raw_mut_ptr();\n        unsafe { &mut (*ptr) }\n    }\n\n    pub fn extract_inst(&self) -> &ClassObject {\n        let class = self.get_class();\n        match &class.kind {\n            oop::ClassKind::Instance(cls_obj) => cls_obj,\n            _ => unreachable!(),\n        }\n    }\n}\n\nimpl Debug for ClassPtr {\n    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {\n        let cls = self.get_class();\n        let cls_name = unsafe { std::str::from_utf8_unchecked(cls.name.as_slice()) };\n        let cls_name = cls_name.to_string();\n        let cls_kind_type = format!(\"{:?}\", cls.get_class_kind_type());\n        let cls_state = format!(\"{:?}\", cls.get_class_state());\n        f.debug_struct(\"ClassPtr\")\n            .field(\"name\", &cls_name)\n            .field(\"state\", &cls_state)\n            .field(\"kind\", &cls_kind_type)\n            .finish()\n    }\n}\n\n/////////////////////////////////////////////\n\npub struct Class {\n    clinit_mutex: Arc<std::sync::Mutex<()>>,\n    mutex: ReentrantMutex,\n    state: std::sync::atomic::AtomicU8,\n\n    pub name: BytesRef,\n    pub acc_flags: U2,\n\n    // None for java.lang.Object\n    pub super_class: Option<ClassRef>,\n\n    // None for the \"bootstrap\" loader\n    pub class_loader: Option<ClassLoader>,\n\n    pub kind: ClassKind,\n}\n\npub enum ClassKind {\n    Instance(ClassObject),\n    ObjectArray(ArrayClassObject),\n    TypeArray(ArrayClassObject),\n}\n\n#[derive(Debug, Copy, Clone, PartialOrd, PartialEq)]\npub enum ClassKindType {\n    Instance,\n    ObjectAry,\n    TypAry,\n}\n\n#[derive(Debug, Copy, Clone, PartialOrd, PartialEq)]\npub enum State {\n    Allocated,\n    Loaded,\n    Linked,\n    BeingIni,\n    FullyIni,\n    IniErr,\n}\n\nimpl From<u8> for State {\n    fn from(v: u8) -> Self {\n        match v {\n            0 => State::Allocated,\n            1 => State::Loaded,\n            2 => State::Linked,\n            3 => State::BeingIni,\n            4 => State::FullyIni,\n            5 => State::IniErr,\n            _ => unreachable!(),\n        }\n    }\n}\n\nimpl Into<u8> for State {\n    fn into(self) -> u8 {\n        match self {\n            State::Allocated => 0,\n            State::Loaded => 1,\n            State::Linked => 2,\n            State::BeingIni => 3,\n            State::FullyIni => 4,\n            State::IniErr => 5,\n        }\n    }\n}\n\npub struct ClassObject {\n    pub class_file: ClassFileRef,\n\n    pub n_inst_fields: usize,\n\n    //  FxHashMap<(name, desc), MethodIdRef>\n    pub all_methods: FxHashMap<(BytesRef, BytesRef), MethodIdRef>,\n    v_table: FxHashMap<(BytesRef, BytesRef), MethodIdRef>,\n\n    //  FxHashMap<(package, name, desc), FieldIdRef>\n    pub static_fields: FxHashMap<(BytesRef, BytesRef, BytesRef), FieldIdRef>,\n    pub inst_fields: FxHashMap<(BytesRef, BytesRef, BytesRef), FieldIdRef>,\n\n    static_field_values: Vec<Oop>,\n\n    interfaces: FxHashMap<BytesRef, ClassRef>,\n\n    mirror: Option<Oop>,\n\n    pub signature: Option<BytesRef>,\n    pub source_file: Option<BytesRef>,\n    pub enclosing_method: Option<EnclosingMethod>,\n    pub inner_classes: Option<Vec<InnerClass>>,\n\n    pub cp_cache: ConstantPoolCache,\n}\n\npub struct ArrayClassObject {\n    pub value_type: ValueType,\n\n    //valid when dimension > 1\n    pub down_type: Option<ClassRef>,\n\n    //valid when it's not TypeArray\n    pub component: Option<ClassRef>,\n\n    pub mirror: Option<Oop>,\n}\n\npub fn init_class(class: &ClassRef) {\n    let need = { class.get_class().get_class_state() == State::Linked };\n    if need {\n        let mut cls = class.get_mut_class();\n        let clinit_mutex = cls.clinit_mutex.clone();\n        let l = clinit_mutex.lock().unwrap();\n\n        cls.set_class_state(State::BeingIni);\n        if let Some(super_class) = &cls.super_class {\n            init_class(super_class);\n            init_class_fully(super_class);\n        }\n\n        match &mut cls.kind {\n            ClassKind::Instance(class_obj) => {\n                class_obj.init_static_fields();\n            }\n\n            _ => cls.set_class_state(State::FullyIni),\n        }\n    }\n}\n\n//invoke \"<clinit>\"\npub fn init_class_fully(class: &ClassRef) {\n    let need = { class.get_class().get_class_state() == State::BeingIni };\n\n    if need {\n        let l = class.get_class().clinit_mutex.lock();\n\n        let (mir, name) = {\n            let mut class = class.get_mut_class();\n            class.set_class_state(State::FullyIni);\n\n            let mir = class.get_this_class_method(&util::S_CLINIT, &util::S_CLINIT_SIG);\n            (mir, class.name.clone())\n        };\n\n        if let Ok(mir) = mir {\n            info!(\"call {}:<clinit>\", unsafe {\n                std::str::from_utf8_unchecked(name.as_slice())\n            });\n            let mut jc = JavaCall::new_with_args(mir, vec![]);\n            jc.invoke(None, true);\n        }\n    }\n}\n\npub fn load_and_init(name: &[u8]) -> ClassRef {\n    // trace!(\"load_and_init 1 name={}\", String::from_utf8_lossy(name));\n    let cls_name = unsafe { std::str::from_utf8_unchecked(name) };\n    let class = runtime::require_class3(None, name)\n        .unwrap_or_else(|| panic!(\"Class not found: {}\", cls_name));\n\n    init_class(&class);\n    init_class_fully(&class);\n\n    class\n}\n\nimpl Class {\n    pub fn get_class_state(&self) -> State {\n        let v = self.state.load(Ordering::Relaxed);\n        State::from(v)\n    }\n\n    pub fn set_class_state(&mut self, s: State) {\n        self.state.store(s.into(), Ordering::Relaxed);\n    }\n\n    pub fn get_name(&self) -> BytesRef {\n        self.name.clone()\n    }\n\n    pub fn get_super_class(&self) -> Option<ClassRef> {\n        self.super_class.clone()\n    }\n\n    pub fn is_public(&self) -> bool {\n        (self.acc_flags & ACC_PUBLIC) == ACC_PUBLIC\n    }\n\n    pub fn is_private(&self) -> bool {\n        (self.acc_flags & ACC_PRIVATE) == ACC_PRIVATE\n    }\n\n    pub fn is_protected(&self) -> bool {\n        (self.acc_flags & ACC_PROTECTED) == ACC_PROTECTED\n    }\n\n    pub fn is_final(&self) -> bool {\n        (self.acc_flags & ACC_FINAL) == ACC_FINAL\n    }\n\n    pub fn is_static(&self) -> bool {\n        (self.acc_flags & ACC_STATIC) == ACC_STATIC\n    }\n\n    pub fn is_abstract(&self) -> bool {\n        (self.acc_flags & ACC_ABSTRACT) == ACC_ABSTRACT\n    }\n\n    pub fn is_interface(&self) -> bool {\n        (self.acc_flags & ACC_INTERFACE) == ACC_INTERFACE\n    }\n\n    pub fn monitor_enter(&self) {\n        unsafe {\n            self.mutex.lock();\n        }\n    }\n\n    pub fn monitor_exit(&self) {\n        unsafe {\n            self.mutex.unlock();\n        }\n    }\n\n    pub fn link_class(&mut self, self_ref: ClassRef) {\n        match &mut self.kind {\n            ClassKind::Instance(class_obj) => {\n                self.super_class = class_obj.link_super_class(self.name.clone(), self.class_loader);\n                let n = match &self.super_class {\n                    Some(super_cls) => {\n                        let super_cls = super_cls.get_class();\n                        match &super_cls.kind {\n                            ClassKind::Instance(cls) => cls.n_inst_fields,\n                            _ => 0,\n                        }\n                    }\n                    None => 0,\n                };\n                class_obj.link_fields(self_ref.clone(), self.name.clone(), n);\n                class_obj.link_interfaces();\n                class_obj.link_methods(self_ref, self.name.clone());\n                class_obj.link_attributes();\n            }\n\n            ClassKind::ObjectArray(ary_class_obj) => {\n                let super_class = runtime::require_class3(None, consts::J_OBJECT).unwrap();\n                self.super_class = Some(super_class);\n            }\n\n            ClassKind::TypeArray(ary_class_obj) => {\n                let super_class = runtime::require_class3(None, consts::J_OBJECT).unwrap();\n                self.super_class = Some(super_class);\n            }\n        }\n\n        self.set_class_state(State::Linked);\n    }\n\n    pub fn get_class_kind_type(&self) -> ClassKindType {\n        match &self.kind {\n            ClassKind::Instance(_) => ClassKindType::Instance,\n            ClassKind::ObjectArray(_) => ClassKindType::ObjectAry,\n            ClassKind::TypeArray(_) => ClassKindType::TypAry,\n        }\n    }\n\n    pub fn is_instance(&self) -> bool {\n        match &self.kind {\n            ClassKind::Instance(_) => true,\n            _ => false,\n        }\n    }\n\n    pub fn is_array(&self) -> bool {\n        match &self.kind {\n            ClassKind::Instance(_) => false,\n            _ => true,\n        }\n    }\n\n    pub fn is_object_ary(&self) -> bool {\n        match &self.kind {\n            ClassKind::Instance(_) => false,\n            ClassKind::TypeArray(_) => false,\n            ClassKind::ObjectArray(_) => true,\n        }\n    }\n\n    pub fn get_mirror(&self) -> Oop {\n        match &self.kind {\n            ClassKind::Instance(cls_obj) => cls_obj.mirror.clone().unwrap(),\n            //[J\n            ClassKind::TypeArray(typ_ary) => typ_ary.mirror.clone().unwrap(),\n            //[Ljava/lang/Object;\n            ClassKind::ObjectArray(obj_ary) => obj_ary.mirror.clone().unwrap(),\n            _ => unreachable!(),\n        }\n    }\n\n    pub fn set_mirror(&mut self, mirror: Oop) {\n        match &mut self.kind {\n            ClassKind::Instance(cls_obj) => cls_obj.mirror = Some(mirror),\n            ClassKind::ObjectArray(obj_ary) => obj_ary.mirror = Some(mirror),\n            ClassKind::TypeArray(typ_ary) => typ_ary.mirror = Some(mirror),\n        }\n    }\n\n    pub fn get_source_file(&self) -> Option<BytesRef> {\n        match &self.kind {\n            ClassKind::Instance(cls_obj) => cls_obj.source_file.clone(),\n            _ => unreachable!(),\n        }\n    }\n\n    pub fn get_annotation(&self) -> Option<Vec<u8>> {\n        match &self.kind {\n            ClassKind::Instance(cls) => {\n                util::attributes::assemble_annotation(&cls.class_file.attrs)\n            }\n            _ => unreachable!(),\n        }\n    }\n\n    pub fn get_type_annotation(&self) -> Option<Vec<u8>> {\n        match &self.kind {\n            ClassKind::Instance(cls) => {\n                util::attributes::assemble_type_annotation(&cls.class_file.attrs)\n            }\n            _ => unreachable!(),\n        }\n    }\n\n    pub fn get_attr_signatrue(&self) -> Option<&BytesRef> {\n        match &self.kind {\n            ClassKind::Instance(cls) => {\n                let idx = util::attributes::get_signature(&cls.class_file.attrs);\n                if idx != 0 {\n                    let cp = &cls.class_file.cp;\n                    let s = get_cp_utf8(cp, idx as usize);\n                    Some(s)\n                } else {\n                    None\n                }\n            }\n            _ => unreachable!(),\n        }\n    }\n}\n\nimpl ArrayClassObject {\n    pub fn get_dimension(&self) -> usize {\n        match self.down_type.as_ref() {\n            Some(down_type) => {\n                let down_type = down_type.get_class();\n                let n = match &down_type.kind {\n                    ClassKind::Instance(_) => unreachable!(),\n                    ClassKind::ObjectArray(ary_cls_obj) => ary_cls_obj.get_dimension(),\n                    ClassKind::TypeArray(ary_cls_obj) => ary_cls_obj.get_dimension(),\n                };\n                1 + n\n            }\n            None => 1,\n        }\n    }\n}\n\n//open api\nimpl Class {\n    //todo: confirm static method\n    pub fn get_static_method(&self, name: &BytesRef, desc: &BytesRef) -> Result<MethodIdRef, ()> {\n        self.get_class_method_inner(name, desc, true)\n    }\n\n    pub fn get_class_method(&self, name: &BytesRef, desc: &BytesRef) -> Result<MethodIdRef, ()> {\n        self.get_class_method_inner(name, desc, true)\n    }\n\n    pub fn get_this_class_method(\n        &self,\n        name: &BytesRef,\n        desc: &BytesRef,\n    ) -> Result<MethodIdRef, ()> {\n        self.get_class_method_inner(name, desc, false)\n    }\n\n    pub fn get_virtual_method(&self, name: &BytesRef, desc: &BytesRef) -> Result<MethodIdRef, ()> {\n        self.get_virtual_method_inner(name, desc)\n    }\n\n    pub fn get_interface_method(\n        &self,\n        name: &BytesRef,\n        desc: &BytesRef,\n    ) -> Result<MethodIdRef, ()> {\n        self.get_interface_method_inner(name, desc)\n    }\n\n    pub fn get_field_id(&self, name: &BytesRef, desc: &BytesRef, is_static: bool) -> FieldIdRef {\n        let k = (self.name.clone(), name.clone(), desc.clone());\n\n        if is_static {\n            match &self.kind {\n                ClassKind::Instance(cls_obj) => {\n                    if let Some(fid) = cls_obj.static_fields.get(&k) {\n                        return fid.clone();\n                    }\n                }\n                _ => unreachable!(),\n            }\n        } else {\n            match &self.kind {\n                ClassKind::Instance(cls_obj) => {\n                    if let Some(fid) = cls_obj.inst_fields.get(&k) {\n                        return fid.clone();\n                    }\n                }\n                _ => unreachable!(),\n            }\n        }\n\n        let super_class = self.super_class.clone();\n        super_class\n            .unwrap()\n            .get_class()\n            .get_field_id(name, desc, is_static)\n    }\n\n    pub fn put_field_value(rf: Arc<OopPtr>, fir: FieldIdRef, v: Oop) {\n        Self::put_field_value2(rf, fir.offset, v);\n    }\n\n    pub fn put_field_value2(rf: Arc<OopPtr>, offset: usize, v: Oop) {\n        let ptr = rf.get_mut_raw_ptr();\n        unsafe {\n            match &mut (*ptr).v {\n                oop::RefKind::Inst(inst) => inst.field_values[offset] = v,\n                oop::RefKind::Mirror(mirror) => mirror.field_values[offset] = v,\n                oop::RefKind::Array(ary) => ary.elements[offset] = v,\n                t => unreachable!(\"t = {:?}\", t),\n            }\n        }\n    }\n\n    pub fn get_field_value(rf: Arc<OopPtr>, fid: FieldIdRef) -> Oop {\n        Self::get_field_value2(rf, fid.offset)\n    }\n\n    pub fn get_field_value2(rf: Arc<OopPtr>, offset: usize) -> Oop {\n        unsafe {\n            let ptr = rf.get_raw_ptr();\n            match &(*ptr).v {\n                oop::RefKind::Inst(inst) => inst.field_values[offset].clone(),\n                oop::RefKind::Mirror(mirror) => match mirror.field_values.get(offset) {\n                    Some(v) => v.clone(),\n                    _ => unreachable!(\"mirror = {:?}\", mirror),\n                },\n                oop::RefKind::Array(ary) => ary.elements[offset].clone(),\n                t => unreachable!(\"t = {:?}\", t),\n            }\n        }\n    }\n\n    pub fn put_static_field_value(&mut self, fid: FieldIdRef, v: Oop) {\n        match &mut self.kind {\n            ClassKind::Instance(cls_obj) => {\n                let k = (\n                    self.name.clone(),\n                    fid.field.name.clone(),\n                    fid.field.desc.clone(),\n                );\n                if cls_obj.static_fields.contains_key(&k) {\n                    cls_obj.static_field_values[fid.offset] = v;\n                } else {\n                    let super_class = self.super_class.clone();\n                    super_class\n                        .unwrap()\n                        .get_mut_class()\n                        .put_static_field_value(fid, v);\n                }\n            }\n            _ => unreachable!(),\n        }\n    }\n\n    pub fn get_static_field_value(&self, fid: FieldIdRef) -> Oop {\n        match &self.kind {\n            ClassKind::Instance(cls_obj) => {\n                let k = (\n                    self.name.clone(),\n                    fid.field.name.clone(),\n                    fid.field.desc.clone(),\n                );\n                if cls_obj.static_fields.contains_key(&k) {\n                    cls_obj.static_field_values[fid.offset].clone()\n                } else {\n                    let super_class = self.super_class.clone();\n                    super_class.unwrap().get_class().get_static_field_value(fid)\n                }\n            }\n            _ => unreachable!(),\n        }\n    }\n\n    pub fn check_interface(&self, intf: ClassRef) -> bool {\n        match &self.kind {\n            ClassKind::Instance(inst) => {\n                for e in inst.interfaces.values() {\n                    if Arc::ptr_eq(e, &intf) {\n                        return true;\n                    }\n\n                    let e = e.get_class();\n                    if e.check_interface(intf.clone()) {\n                        return true;\n                    }\n                }\n            }\n            _ => unreachable!(),\n        }\n\n        match &self.super_class {\n            Some(super_cls) => {\n                let super_cls = super_cls.get_class();\n                super_cls.check_interface(intf)\n            }\n            None => false,\n        }\n    }\n\n    pub fn hack_as_native(&mut self, name: &[u8], desc: &[u8]) {\n        match &mut self.kind {\n            ClassKind::Instance(cls) => {\n                let m = {\n                    let name = Arc::new(Vec::from(name));\n                    let desc = Arc::new(Vec::from(desc));\n                    let k = (name, desc);\n                    let it = cls.all_methods.get_mut(&k).unwrap();\n                    let mut method = it.method.clone();\n                    method.acc_flags |= ACC_NATIVE;\n                    let m = method::MethodId::new(it.offset, method);\n                    cls.all_methods.insert(k, m.clone());\n\n                    m\n                };\n\n                info!(\n                    \"hack_as_native: {}:{}:{}, native={}\",\n                    unsafe { std::str::from_utf8_unchecked(self.name.as_slice()) },\n                    unsafe { std::str::from_utf8_unchecked(name) },\n                    unsafe { std::str::from_utf8_unchecked(desc) },\n                    m.method.is_native()\n                );\n            }\n            _ => unreachable!(),\n        }\n    }\n}\n\n//open api new\nimpl Class {\n    pub fn new_class(class_file: ClassFileRef, class_loader: Option<ClassLoader>) -> Self {\n        let cp = class_file.cp.clone();\n        let name = constant_pool::get_class_name(&cp, class_file.this_class as usize).clone();\n        let acc_flags = class_file.acc_flags;\n        let class_obj = ClassObject {\n            class_file,\n            n_inst_fields: 0,\n            all_methods: FxHashMap::default(),\n            v_table: FxHashMap::default(),\n            static_fields: FxHashMap::default(),\n            inst_fields: FxHashMap::default(),\n            static_field_values: vec![],\n            interfaces: FxHashMap::default(),\n            mirror: None,\n            signature: None,\n            source_file: None,\n            enclosing_method: None,\n            inner_classes: None,\n            cp_cache: ConstantPoolCache::new(cp),\n        };\n\n        let mutex = unsafe {\n            let mut mutex = ReentrantMutex::uninitialized();\n            mutex.init();\n            mutex\n        };\n\n        Self {\n            clinit_mutex: Arc::new(Mutex::new(())),\n            name,\n            state: std::sync::atomic::AtomicU8::new(State::Allocated.into()),\n            acc_flags,\n            super_class: None,\n            class_loader,\n            kind: ClassKind::Instance(class_obj),\n            mutex,\n        }\n    }\n\n    pub fn new_object_ary(class_loader: ClassLoader, component: ClassRef, elm_name: &[u8]) -> Self {\n        let name = Vec::from(elm_name);\n        let name = Arc::new(name);\n\n        let ary_cls_obj = ArrayClassObject {\n            value_type: ValueType::ARRAY,\n            down_type: None,\n            component: Some(component),\n            mirror: None,\n        };\n\n        let mutex = unsafe {\n            let mut mutex = ReentrantMutex::uninitialized();\n            mutex.init();\n            mutex\n        };\n\n        Self {\n            clinit_mutex: Arc::new(Mutex::new(())),\n            name,\n            state: std::sync::atomic::AtomicU8::new(State::Allocated.into()),\n            acc_flags: 0, //todo: should be 0?\n            super_class: None,\n            class_loader: Some(class_loader),\n            kind: ClassKind::ObjectArray(ary_cls_obj),\n            mutex,\n        }\n    }\n\n    pub fn new_prime_ary(class_loader: ClassLoader, value_type: ValueType) -> Self {\n        let ary_cls_obj = ArrayClassObject {\n            value_type,\n            down_type: None,\n            component: None,\n            mirror: None,\n        };\n\n        let mut name = Vec::with_capacity(2);\n        name.push(b'[');\n        name.extend_from_slice(value_type.into());\n\n        let mutex = unsafe {\n            let mut mutex = ReentrantMutex::uninitialized();\n            mutex.init();\n            mutex\n        };\n\n        Self {\n            clinit_mutex: Arc::new(Mutex::new(())),\n            name: Arc::new(name),\n            state: std::sync::atomic::AtomicU8::new(State::Allocated.into()),\n            acc_flags: 0, //todo: should be 0?\n            super_class: None,\n            class_loader: Some(class_loader),\n            kind: ClassKind::TypeArray(ary_cls_obj),\n            mutex,\n        }\n    }\n\n    pub fn new_wrapped_ary(class_loader: ClassLoader, down_type: ClassRef) -> Self {\n        let cls = down_type.get_class();\n        debug_assert!(cls.is_array());\n\n        //build name\n        let mut name2 = Vec::with_capacity(1 + cls.name.len());\n        name2.push(b'[');\n        name2.extend_from_slice(cls.name.as_slice());\n\n        let kind = match cls.get_class_kind_type() {\n            ClassKindType::Instance => unreachable!(),\n            ClassKindType::TypAry => ClassKind::TypeArray(ArrayClassObject {\n                value_type: ValueType::ARRAY,\n                down_type: Some(down_type),\n                component: None,\n                mirror: None,\n            }),\n            ClassKindType::ObjectAry => {\n                let component = {\n                    let cls = down_type.get_class();\n                    match &cls.kind {\n                        ClassKind::ObjectArray(ary_cls) => ary_cls.component.clone(),\n                        _ => unreachable!(),\n                    }\n                };\n                ClassKind::ObjectArray(ArrayClassObject {\n                    value_type: ValueType::ARRAY,\n                    down_type: Some(down_type),\n                    component,\n                    mirror: None,\n                })\n            }\n        };\n\n        let mutex = unsafe {\n            let mut mutex = ReentrantMutex::uninitialized();\n            mutex.init();\n            mutex\n        };\n\n        Self {\n            clinit_mutex: Arc::new(Mutex::new(())),\n            name: Arc::new(name2),\n            state: std::sync::atomic::AtomicU8::new(State::Allocated.into()),\n            acc_flags: 0, //todo: should be 0?\n            super_class: None,\n            class_loader: Some(class_loader),\n            kind,\n            mutex,\n        }\n    }\n}\n\n//inner api for link\nimpl ClassObject {\n    fn link_super_class(\n        &mut self,\n        name: BytesRef,\n        class_loader: Option<ClassLoader>,\n    ) -> Option<ClassRef> {\n        let class_file = &self.class_file;\n        let cp = &class_file.cp;\n\n        if class_file.super_class == 0 {\n            if name.as_slice() != consts::J_OBJECT {\n                unreachable!(\"should be java/lang/Object\");\n            }\n\n            None\n        } else {\n            let name = constant_pool::get_class_name(cp, class_file.super_class as usize);\n            let super_class = runtime::require_class(class_loader, name).unwrap();\n\n            {\n                let c = super_class.get_class();\n                debug_assert!(c.is_instance());\n                debug_assert!(!c.is_final(), \"should not final\");\n            }\n\n            Some(super_class)\n        }\n    }\n\n    fn link_fields(&mut self, self_ref: ClassRef, cls_name: BytesRef, num_field_of_super: usize) {\n        let cls_file = self.class_file.clone();\n        let cp = &cls_file.cp;\n\n        let mut n_static = 0;\n        let mut offset_field = num_field_of_super;\n\n        cls_file.fields.iter().for_each(|it| {\n            let field = field::Field::new(cp, it, cls_name.clone(), self_ref.clone());\n            let k = (cls_name.clone(), field.name.clone(), field.desc.clone());\n\n            if field.is_static() {\n                let fid = field::FieldId {\n                    offset: n_static,\n                    field,\n                };\n\n                self.static_fields.insert(k, Arc::new(fid));\n                n_static += 1;\n            } else {\n                let fid = field::FieldId {\n                    offset: offset_field,\n                    field,\n                };\n\n                self.inst_fields.insert(k, Arc::new(fid));\n                offset_field += 1;\n            }\n        });\n\n        self.n_inst_fields = offset_field;\n        self.static_field_values = vec![Oop::Null; n_static];\n    }\n\n    fn link_interfaces(&mut self) {\n        let class_file = self.class_file.clone();\n        let cp = &class_file.cp;\n\n        class_file\n            .interfaces\n            .iter()\n            .for_each(|it| match runtime::require_class2(*it, cp) {\n                Some(class) => {\n                    let name = class.get_class().name.clone();\n                    self.interfaces.insert(name, class);\n                }\n                None => {\n                    let name = constant_pool::get_class_name(cp, *it as usize);\n                    error!(\"link interface failed {:?}\", name);\n                }\n            });\n    }\n\n    fn link_methods(&mut self, this_ref: ClassRef, cls_name: BytesRef) {\n        let class_file = self.class_file.clone();\n        let cp = &class_file.cp;\n\n        class_file.methods.iter().enumerate().for_each(|(i, it)| {\n            let method = method::Method::new(\n                cp,\n                it,\n                this_ref.clone(),\n                class_file.clone(),\n                i,\n                cls_name.clone(),\n            );\n            let method_id = method::MethodId::new(i, method);\n            let name = method_id.method.name.clone();\n            let desc = method_id.method.desc.clone();\n            let k = (name, desc);\n            self.all_methods.insert(k.clone(), method_id.clone());\n\n            if !method_id.method.is_static() {\n                self.v_table.insert(k, method_id);\n            }\n        });\n    }\n\n    fn link_attributes(&mut self) {\n        let class_file = self.class_file.clone();\n        let cp = &class_file.cp;\n\n        class_file.attrs.iter().for_each(|a| match a {\n            AttributeType::Signature { signature_index } => {\n                let s = get_cp_utf8(cp, *signature_index as usize);\n                self.signature = Some(s.clone());\n            }\n            AttributeType::SourceFile { source_file_index } => {\n                let s = get_cp_utf8(cp, *source_file_index as usize);\n                self.source_file = Some(s.clone());\n            }\n            AttributeType::EnclosingMethod { em } => {\n                self.enclosing_method = Some(em.clone());\n            }\n            AttributeType::InnerClasses { classes } => {\n                self.inner_classes = Some(classes.clone());\n            }\n            _ => (),\n        });\n    }\n\n    fn init_static_fields(&mut self) {\n        let values = &mut self.static_field_values;\n        self.static_fields.iter().for_each(|(_, it)| {\n            if it.field.is_final() {\n                match it.field.get_attr_constant_value() {\n                    Some(v) => values[it.offset] = v,\n                    None => values[it.offset] = it.field.get_constant_value(),\n                }\n            } else {\n                values[it.offset] = it.field.get_constant_value();\n            }\n        });\n    }\n}\n\nimpl Class {\n    pub fn get_class_method_inner(\n        &self,\n        name: &BytesRef,\n        desc: &BytesRef,\n        with_super: bool,\n    ) -> Result<MethodIdRef, ()> {\n        let k = (name.clone(), desc.clone());\n        match &self.kind {\n            ClassKind::Instance(cls_obj) => {\n                if let Some(m) = cls_obj.all_methods.get(&k) {\n                    return Ok(m.clone());\n                }\n            }\n            ClassKind::ObjectArray(ary) => {\n                //use java/lang/Object, methods\n            }\n            _ => unreachable!(),\n        }\n\n        if with_super {\n            match self.super_class.as_ref() {\n                Some(super_class) => {\n                    return super_class\n                        .get_class()\n                        .get_class_method_inner(name, desc, with_super);\n                }\n                None => return Err(()),\n            }\n        }\n\n        Err(())\n    }\n\n    fn get_virtual_method_inner(\n        &self,\n        name: &BytesRef,\n        desc: &BytesRef,\n    ) -> Result<MethodIdRef, ()> {\n        let k = (name.clone(), desc.clone());\n        match &self.kind {\n            ClassKind::Instance(cls_obj) => {\n                if let Some(m) = cls_obj.v_table.get(&k) {\n                    return Ok(m.clone());\n                }\n            }\n            _ => unreachable!(),\n        }\n\n        match self.super_class.as_ref() {\n            Some(super_class) => super_class.get_class().get_virtual_method_inner(name, desc),\n            None => Err(()),\n        }\n    }\n\n    pub fn get_interface_method_inner(\n        &self,\n        name: &BytesRef,\n        desc: &BytesRef,\n    ) -> Result<MethodIdRef, ()> {\n        let k = (name.clone(), desc.clone());\n        match &self.kind {\n            ClassKind::Instance(cls_obj) => match cls_obj.v_table.get(&k) {\n                Some(m) => return Ok(m.clone()),\n                None => {\n                    for (_, itf) in cls_obj.interfaces.iter() {\n                        let cls = itf.get_class();\n                        let m = cls.get_interface_method(name, desc);\n                        if m.is_ok() {\n                            return m;\n                        }\n                    }\n                }\n            },\n            _ => unreachable!(),\n        }\n\n        match self.super_class.as_ref() {\n            Some(super_class) => super_class\n                .get_class()\n                .get_interface_method_inner(name, desc),\n            None => Err(()),\n        }\n    }\n}\n"
  },
  {
    "path": "crates/vm/src/oop/consts.rs",
    "content": "use crate::oop::Oop;\nuse std::sync::Arc;\n\nlazy_static! {\n    static ref INT0: Oop = { Oop::new_int(0) };\n    static ref LONG0: Oop = { Oop::new_long(0) };\n    static ref FLOAT0: Oop = { Oop::new_float(0.0) };\n    static ref DOUBLE0: Oop = { Oop::new_double(0.0) };\n}\n\npub fn get_int0() -> Oop {\n    INT0.clone()\n}\n\npub fn get_long0() -> Oop {\n    LONG0.clone()\n}\n\npub fn get_float0() -> Oop {\n    FLOAT0.clone()\n}\n\npub fn get_double0() -> Oop {\n    DOUBLE0.clone()\n}\n\npub fn init() {\n    lazy_static::initialize(&INT0);\n    lazy_static::initialize(&LONG0);\n    lazy_static::initialize(&FLOAT0);\n    lazy_static::initialize(&DOUBLE0);\n}\n"
  },
  {
    "path": "crates/vm/src/oop/field.rs",
    "content": "use crate::oop::{self, consts as oop_consts, Oop, ValueType};\nuse crate::runtime::require_class2;\nuse crate::types::ClassRef;\nuse crate::types::*;\nuse crate::util;\nuse crate::util::PATH_SEP;\nuse classfile::{\n    constant_pool, consts, flags::*, AttributeType, BytesRef, ConstantPool, ConstantPoolType,\n    FieldInfo, U2,\n};\nuse std::fmt;\nuse std::ops::Deref;\nuse std::sync::Arc;\n\npub fn get_field_ref(cp: &ConstantPool, idx: usize, is_static: bool) -> FieldIdRef {\n    let (class_index, name_and_type_index) = constant_pool::get_field_ref(cp, idx);\n\n    //load Field's Class, then init it\n    let class = require_class2(class_index, cp).unwrap_or_else(|| {\n        panic!(\n            \"Unknown field class {:?}\",\n            cp.get(class_index as usize)\n                .expect(\"Missing item\")\n                .as_cp_item(cp)\n        )\n    });\n\n    oop::class::init_class(&class);\n    oop::class::init_class_fully(&class);\n\n    let (name, desc) = constant_pool::get_name_and_type(cp, name_and_type_index as usize);\n    let class = class.get_class();\n    class.get_field_id(name, desc, is_static)\n}\n\npub fn build_inited_field_values(class: ClassRef) -> Vec<Oop> {\n    let n = {\n        let class = class.get_class();\n        match &class.kind {\n            oop::class::ClassKind::Instance(class_obj) => class_obj.n_inst_fields,\n            _ => unreachable!(),\n        }\n    };\n    let mut field_values = vec![Oop::Null; n];\n    let mut cur_cls = class;\n\n    loop {\n        let cls = cur_cls.clone();\n        let cls = cls.get_class();\n        match &cls.kind {\n            oop::class::ClassKind::Instance(cls_obj) => {\n                cls_obj.inst_fields.iter().for_each(|(_, fir)| {\n                    match fir.field.value_type {\n                        ValueType::BYTE\n                        | ValueType::BOOLEAN\n                        | ValueType::CHAR\n                        | ValueType::SHORT\n                        | ValueType::INT => {\n                            field_values[fir.offset] = oop_consts::get_int0();\n                        }\n                        ValueType::LONG => {\n                            field_values[fir.offset] = oop_consts::get_long0();\n                        }\n                        ValueType::FLOAT => {\n                            field_values[fir.offset] = oop_consts::get_float0();\n                        }\n                        ValueType::DOUBLE => {\n                            field_values[fir.offset] = oop_consts::get_double0();\n                        }\n                        ValueType::OBJECT | ValueType::ARRAY => {\n                            //ignore, has been inited by NULL\n                        }\n                        ValueType::VOID => unreachable!(),\n                    }\n                });\n            }\n            _ => unreachable!(),\n        }\n\n        if cls.super_class.is_none() {\n            break;\n        } else {\n            cur_cls = cls.super_class.clone().unwrap();\n        }\n    }\n\n    field_values\n}\n\n#[derive(Debug, Clone)]\npub struct FieldId {\n    pub offset: usize,\n    pub field: Field,\n}\n\n#[derive(Clone)]\npub struct Field {\n    pub class: ClassRef,\n    pub cls_name: BytesRef,\n    pub name: BytesRef,\n    pub desc: BytesRef,\n    pub acc_flags: U2,\n    pub value_type: ValueType,\n    pub attr_constant_value: Option<Oop>,\n}\n\nimpl Field {\n    pub fn new(cp: &ConstantPool, fi: &FieldInfo, cls_name: BytesRef, class: ClassRef) -> Self {\n        let name = constant_pool::get_utf8(cp, fi.name_index as usize).clone();\n        let desc = constant_pool::get_utf8(cp, fi.desc_index as usize).clone();\n        let value_type = desc.first().unwrap().into();\n        let acc_flags = fi.acc_flags;\n\n        let mut attr_constant_value = None;\n        for it in fi.attrs.iter() {\n            if let AttributeType::ConstantValue {\n                constant_value_index,\n            } = it\n            {\n                let v = constant_value(cp, *constant_value_index as usize);\n                attr_constant_value = Some(v);\n                break;\n            }\n        }\n\n        Self {\n            class,\n            cls_name,\n            name,\n            desc,\n            acc_flags,\n            value_type,\n            attr_constant_value,\n        }\n    }\n\n    pub fn is_public(&self) -> bool {\n        (self.acc_flags & ACC_PUBLIC) == ACC_PUBLIC\n    }\n\n    pub fn is_private(&self) -> bool {\n        (self.acc_flags & ACC_PRIVATE) == ACC_PRIVATE\n    }\n\n    pub fn is_protected(&self) -> bool {\n        (self.acc_flags & ACC_PROTECTED) == ACC_PROTECTED\n    }\n\n    pub fn is_final(&self) -> bool {\n        (self.acc_flags & ACC_FINAL) == ACC_FINAL\n    }\n\n    pub fn is_static(&self) -> bool {\n        (self.acc_flags & ACC_STATIC) == ACC_STATIC\n    }\n\n    pub fn is_volatile(&self) -> bool {\n        (self.acc_flags & ACC_VOLATILE) == ACC_VOLATILE\n    }\n\n    pub fn get_constant_value(&self) -> Oop {\n        match self.value_type {\n            ValueType::BYTE\n            | ValueType::BOOLEAN\n            | ValueType::CHAR\n            | ValueType::SHORT\n            | ValueType::INT => oop_consts::get_int0(),\n            ValueType::LONG => oop_consts::get_long0(),\n            ValueType::FLOAT => oop_consts::get_float0(),\n            ValueType::DOUBLE => oop_consts::get_double0(),\n            ValueType::OBJECT | ValueType::ARRAY => Oop::Null,\n            _ => unreachable!(),\n        }\n    }\n\n    pub fn get_attr_constant_value(&self) -> Option<Oop> {\n        self.attr_constant_value.clone()\n    }\n}\n\nimpl fmt::Debug for Field {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        let cls_name = unsafe { std::str::from_utf8_unchecked(self.cls_name.as_slice()) };\n        let name = unsafe { std::str::from_utf8_unchecked(self.name.as_slice()) };\n        let desc = unsafe { std::str::from_utf8_unchecked(self.desc.as_slice()) };\n        write!(f, \"{}:{}:{}\", cls_name, name, desc)\n    }\n}\n\nfn constant_value(cp: &ConstantPool, v_idx: usize) -> Oop {\n    match cp.get(v_idx) {\n        Some(ConstantPoolType::Long { v }) => {\n            let v = i64::from_be_bytes(*v);\n            Oop::new_long(v)\n        }\n        Some(ConstantPoolType::Float { v }) => {\n            let v = u32::from_be_bytes(*v);\n            let v = f32::from_bits(v);\n            Oop::new_float(v)\n        }\n        Some(ConstantPoolType::Double { v }) => {\n            let v = u64::from_be_bytes(*v);\n            let v = f64::from_bits(v);\n            Oop::new_double(v)\n        }\n        Some(ConstantPoolType::Integer { v }) => {\n            let v = i32::from_be_bytes(*v);\n            Oop::new_int(v)\n        }\n        Some(ConstantPoolType::String { string_index }) => {\n            let v = constant_pool::get_utf8(cp, *string_index as usize).clone();\n            Oop::new_const_utf8(v)\n        }\n        _ => unreachable!(),\n    }\n}\n"
  },
  {
    "path": "crates/vm/src/oop/inst.rs",
    "content": "use crate::oop::{field, Oop};\nuse crate::types::ClassRef;\n\n#[derive(Debug, Clone)]\npub struct InstOopDesc {\n    pub class: ClassRef,\n    pub field_values: Vec<Oop>,\n}\n\nimpl InstOopDesc {\n    pub fn new(class: ClassRef) -> Self {\n        let field_values = field::build_inited_field_values(class.clone());\n\n        Self {\n            class,\n            field_values,\n        }\n    }\n}\n"
  },
  {
    "path": "crates/vm/src/oop/mirror.rs",
    "content": "use crate::oop::{Oop, ValueType};\nuse crate::types::ClassRef;\n\n#[derive(Debug, Clone)]\npub struct MirrorOopDesc {\n    pub target: Option<ClassRef>,\n    pub field_values: Vec<Oop>,\n    pub value_type: ValueType,\n}\n\nimpl MirrorOopDesc {\n    pub fn is_prim_mirror(&self) -> bool {\n        self.target.is_none()\n    }\n}\n"
  },
  {
    "path": "crates/vm/src/oop/mod.rs",
    "content": "#![allow(unused)]\n\nuse std::fmt;\nuse std::sync::{Arc, Condvar, Mutex, RwLock};\n\nuse classfile::{BytesRef, ClassFile};\n\nuse crate::new_br;\nuse crate::oop::class::ClassObject;\nuse crate::runtime::{require_class3, ClassLoader};\nuse crate::types::*;\nuse crate::util::oop::{get_java_lang_integer_value_offset, get_java_lang_string_value_offset};\n\npub use self::ary::{ArrayOopDesc, TypeArrayDesc, TypeArrayEnum};\npub use self::class::{Class, ClassKind};\npub use self::inst::InstOopDesc;\npub use self::mirror::MirrorOopDesc;\npub use self::reference::{RefKind, RefKindDesc};\npub use self::values::ValueType;\n\npub mod ary;\npub mod class;\npub mod consts;\npub mod field;\npub mod inst;\npub mod mirror;\npub mod reference;\npub mod values;\n\n#[derive(Clone)]\npub enum Oop {\n    Int(i32),\n    Long(i64),\n    Float(f32),\n    Double(f64),\n    /*\n        used by: Throwable.java\n    private static final String NULL_CAUSE_MESSAGE = \"Cannot suppress a null exception.\";\n        */\n    ConstUtf8(BytesRef),\n    //used by oop::field::Filed::get_constant_value\n    Null,\n\n    Ref(Arc<OopPtr>),\n}\n\n#[derive(Debug)]\npub struct OopPtr(u64);\n\nimpl fmt::Debug for Oop {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match self {\n            Oop::Int(v) => write!(f, \"Oop(Int({}))\", *v),\n            Oop::Long(v) => write!(f, \"Oop(Long({}))\", *v),\n            Oop::Float(v) => write!(f, \"Oop(Float({}))\", *v),\n            Oop::Double(v) => write!(f, \"Oop(Double({}))\", *v),\n            Oop::ConstUtf8(v) => write!(\n                f,\n                \"Oop(ConstUtf8({}))\",\n                String::from_utf8_lossy(v.as_slice())\n            ),\n            Oop::Null => write!(f, \"Oop(Null)\"),\n            Oop::Ref(rf) => {\n                let ptr = rf.get_raw_ptr();\n                unsafe {\n                    match &(*ptr).v {\n                        RefKind::Array(ary) => write!(f, \"Oop(OopRef(Array))\"),\n                        RefKind::Inst(inst) => write!(f, \"Oop(OopRef(Instance))\"),\n                        RefKind::TypeArray(ary) => write!(f, \"Oop(OopRef(TypeArray))\"),\n                        RefKind::Mirror(mirror) => write!(f, \"Oop(OopRef(Mirror))\"),\n                    }\n                }\n            }\n        }\n    }\n}\n\n//primitive value factor\nimpl Oop {\n    pub fn new_int(v: i32) -> Self {\n        Oop::Int(v)\n    }\n\n    pub fn new_long(v: i64) -> Self {\n        Oop::Long(v)\n    }\n\n    pub fn new_float(v: f32) -> Self {\n        Oop::Float(v)\n    }\n\n    pub fn new_double(v: f64) -> Self {\n        Oop::Double(v)\n    }\n}\n\n//primitive ary value factor\nimpl Oop {\n    pub fn new_type_ary(v: u8, len: usize) -> Oop {\n        match TypeArrayEnum::from(v) {\n            TypeArrayEnum::Boolean => Self::new_bool_ary(len),\n            TypeArrayEnum::Char => Self::new_char_ary(len),\n            TypeArrayEnum::Float => Self::new_float_ary(len),\n            TypeArrayEnum::Double => Self::new_double_ary(len),\n            TypeArrayEnum::Byte => Self::new_byte_ary(len),\n            TypeArrayEnum::Short => Self::new_short_ary(len),\n            TypeArrayEnum::Int => Self::new_int_ary(len),\n            TypeArrayEnum::Long => Self::new_long_ary(len),\n        }\n    }\n\n    pub fn char_ary_from1(v: &[u16]) -> Oop {\n        let elms = Vec::from(v);\n        Self::new_char_ary2(elms)\n    }\n\n    pub fn new_byte_ary(len: usize) -> Oop {\n        let elms = vec![0; len];\n        Self::new_byte_ary2(elms)\n    }\n\n    fn new_bool_ary(len: usize) -> Oop {\n        let elms = vec![0; len];\n        Self::new_bool_ary2(elms)\n    }\n\n    fn new_char_ary(len: usize) -> Oop {\n        let elms = vec![0; len];\n        Self::new_char_ary2(elms)\n    }\n\n    fn new_short_ary(len: usize) -> Oop {\n        let elms = vec![0; len];\n        Self::new_short_ary2(elms)\n    }\n\n    fn new_int_ary(len: usize) -> Oop {\n        let elms = vec![0; len];\n        Self::new_int_ary2(elms)\n    }\n\n    fn new_float_ary(len: usize) -> Oop {\n        let elms = vec![0.0; len];\n        Self::new_float_ary2(elms)\n    }\n\n    fn new_double_ary(len: usize) -> Oop {\n        let elms = vec![0.0; len];\n        Self::new_double_ary2(elms)\n    }\n\n    fn new_long_ary(len: usize) -> Oop {\n        let elms = vec![0; len];\n        Self::new_long_ary2(elms)\n    }\n\n    pub fn new_byte_ary2(elms: Vec<u8>) -> Oop {\n        let ary = Box::new(elms);\n        let v = TypeArrayDesc::Byte(ary);\n        Self::new_ref(RefKind::TypeArray(v))\n    }\n\n    pub fn new_bool_ary2(elms: Vec<u8>) -> Oop {\n        let ary = Box::new(elms);\n        let v = TypeArrayDesc::Bool(ary);\n        Self::new_ref(RefKind::TypeArray(v))\n    }\n\n    pub fn new_char_ary2(elms: Vec<u16>) -> Oop {\n        let ary = Box::new(elms);\n        let v = TypeArrayDesc::Char(ary);\n        Self::new_ref(RefKind::TypeArray(v))\n    }\n\n    pub fn new_short_ary2(elms: Vec<i16>) -> Oop {\n        let ary = Box::new(elms);\n        let v = TypeArrayDesc::Short(ary);\n        Self::new_ref(RefKind::TypeArray(v))\n    }\n\n    pub fn new_int_ary2(elms: Vec<i32>) -> Oop {\n        let ary = Box::new(elms);\n        let v = TypeArrayDesc::Int(ary);\n        Self::new_ref(RefKind::TypeArray(v))\n    }\n\n    pub fn new_float_ary2(elms: Vec<f32>) -> Oop {\n        let ary = Box::new(elms);\n        let v = TypeArrayDesc::Float(ary);\n        Self::new_ref(RefKind::TypeArray(v))\n    }\n\n    pub fn new_double_ary2(elms: Vec<f64>) -> Oop {\n        let ary = Box::new(elms);\n        let v = TypeArrayDesc::Double(ary);\n        Self::new_ref(RefKind::TypeArray(v))\n    }\n\n    pub fn new_long_ary2(elms: Vec<i64>) -> Oop {\n        let ary = Box::new(elms);\n        let v = TypeArrayDesc::Long(ary);\n        Self::new_ref(RefKind::TypeArray(v))\n    }\n}\n\n//reference value factory\nimpl Oop {\n    pub fn new_const_utf8(v: BytesRef) -> Self {\n        Oop::ConstUtf8(v)\n    }\n\n    pub fn new_null() -> Self {\n        Oop::Null\n    }\n\n    pub fn new_inst(cls_obj: ClassRef) -> Oop {\n        let v = InstOopDesc::new(cls_obj);\n        Self::new_ref(RefKind::Inst(v))\n    }\n}\n\n//mirror\nimpl Oop {\n    pub fn new_mirror(target: ClassRef) -> Oop {\n        let java_lang_class = require_class3(None, b\"java/lang/Class\").unwrap();\n        let field_values = field::build_inited_field_values(java_lang_class);\n        let v = MirrorOopDesc {\n            target: Some(target),\n            field_values,\n            value_type: ValueType::OBJECT,\n        };\n\n        Self::new_ref(RefKind::Mirror(v))\n    }\n\n    pub fn new_prim_mirror(value_type: ValueType, target: Option<ClassRef>) -> Oop {\n        let java_lang_class = require_class3(None, b\"java/lang/Class\").unwrap();\n        let field_values = field::build_inited_field_values(java_lang_class);\n        let v = MirrorOopDesc {\n            target,\n            field_values,\n            value_type,\n        };\n\n        Self::new_ref(RefKind::Mirror(v))\n    }\n\n    pub fn new_ary_mirror(target: ClassRef, value_type: ValueType) -> Oop {\n        let java_lang_class = require_class3(None, b\"java/lang/Class\").unwrap();\n        let field_values = field::build_inited_field_values(java_lang_class);\n        let v = MirrorOopDesc {\n            target: Some(target),\n            field_values: vec![],\n            value_type,\n        };\n\n        Self::new_ref(RefKind::Mirror(v))\n    }\n}\n\n//array reference factory\nimpl Oop {\n    pub fn new_ref_ary(ary_cls_obj: ClassRef, len: usize) -> Oop {\n        let elements = vec![Oop::Null; len];\n        Self::new_ref_ary2(ary_cls_obj, elements)\n    }\n\n    pub fn new_ref_ary2(ary_cls_obj: ClassRef, elms: Vec<Oop>) -> Oop {\n        let v = ArrayOopDesc::new(ary_cls_obj, elms);\n        Self::new_ref(RefKind::Array(v))\n    }\n}\n\n//private helper\nimpl Oop {\n    fn new_ref(v: RefKind) -> Oop {\n        let v = RefKindDesc::new(v);\n        let v = Box::new(v);\n        let ptr = Box::into_raw(v) as u64;\n        let rf = Arc::new(OopPtr(ptr));\n        Oop::Ref(rf)\n    }\n}\n\nimpl Oop {\n    pub fn hash_code(&self) -> i32 {\n        match self {\n            Oop::Ref(rf) => {\n                if OopPtr::is_java_lang_string(rf.clone()) {\n                    OopPtr::java_lang_string_hash(rf.clone())\n                } else {\n                    rf.0 as i32\n                }\n            }\n            Oop::Null => 0,\n            _ => unreachable!(),\n        }\n    }\n}\n\nimpl Oop {\n    pub fn is_null(&self) -> bool {\n        match self {\n            Oop::Null => true,\n            _ => false,\n        }\n    }\n\n    #[inline]\n    pub fn extract_int(&self) -> i32 {\n        match self {\n            Oop::Int(v) => *v,\n            _ => unreachable!(),\n        }\n    }\n\n    #[inline]\n    pub fn extract_float(&self) -> f32 {\n        match &self {\n            Oop::Float(v) => *v,\n            _ => unreachable!(),\n        }\n    }\n\n    #[inline]\n    pub fn extract_long(&self) -> i64 {\n        match self {\n            Oop::Long(v) => *v,\n            _ => unreachable!(),\n        }\n    }\n\n    #[inline]\n    pub fn extract_double(&self) -> f64 {\n        match self {\n            Oop::Double(v) => *v,\n            _ => unreachable!(),\n        }\n    }\n\n    #[inline]\n    pub fn extract_ref(&self) -> Arc<OopPtr> {\n        match self {\n            Oop::Ref(v) => v.clone(),\n            t => unreachable!(\"t = {:?}\", t),\n        }\n    }\n}\n\nimpl OopPtr {\n    pub fn get_raw_ptr(&self) -> *const RefKindDesc {\n        self.0 as *const RefKindDesc\n    }\n\n    pub fn get_mut_raw_ptr(&self) -> *mut RefKindDesc {\n        self.0 as *mut RefKindDesc\n    }\n}\n\nimpl OopPtr {\n    pub fn extract_inst(&self) -> &InstOopDesc {\n        let ptr = self.get_raw_ptr();\n        unsafe { (*ptr).v.extract_inst() }\n    }\n\n    pub fn extract_array(&self) -> &ArrayOopDesc {\n        let ptr = self.get_raw_ptr();\n        unsafe { (*ptr).v.extract_array() }\n    }\n\n    pub fn extract_mut_array(&self) -> &mut ArrayOopDesc {\n        let ptr = self.get_mut_raw_ptr();\n        unsafe { (*ptr).v.extract_mut_array() }\n    }\n\n    pub fn extract_type_array(&self) -> &TypeArrayDesc {\n        let ptr = self.get_raw_ptr();\n        unsafe { (*ptr).v.extract_type_array() }\n    }\n\n    pub fn extract_mut_type_array(&self) -> &mut TypeArrayDesc {\n        let ptr = self.get_mut_raw_ptr();\n        unsafe { (*ptr).v.extract_mut_type_array() }\n    }\n\n    pub fn extract_mirror(&self) -> &MirrorOopDesc {\n        let ptr = self.get_raw_ptr();\n        unsafe { (*ptr).v.extract_mirror() }\n    }\n}\n\nimpl OopPtr {\n    pub fn monitor_enter(&self) {\n        let ptr = self.get_raw_ptr();\n        unsafe { (*ptr).monitor_enter() };\n    }\n\n    pub fn monitor_exit(&self) {\n        let ptr = self.get_raw_ptr();\n        unsafe { (*ptr).monitor_exit() };\n    }\n\n    pub fn notify_all(&self) {\n        let ptr = self.get_raw_ptr();\n        unsafe { (*ptr).notify_all() }\n    }\n\n    pub fn wait(&self) {\n        let ptr = self.get_raw_ptr();\n        unsafe { (*ptr).wait() }\n    }\n\n    pub fn wait_timeout(&self, duration: std::time::Duration) {\n        let ptr = self.get_raw_ptr();\n        unsafe { (*ptr).wait_timeout(duration) }\n    }\n}\n\nimpl OopPtr {\n    pub fn is_eq(l: &Oop, r: &Oop) -> bool {\n        let l_is_null = l.is_null();\n        let r_is_null = r.is_null();\n\n        match (l_is_null, r_is_null) {\n            (true, true) => return true,\n            (true, false) => return false,\n            (false, true) => return false,\n            (false, false) => (),\n        }\n\n        let l = l.extract_ref();\n        let r = r.extract_ref();\n\n        if l.0 == r.0 {\n            true\n        } else if Self::is_java_lang_string(l.clone()) && Self::is_java_lang_string(r.clone()) {\n            Self::is_java_lang_string_eq(l, r)\n        } else {\n            false\n        }\n    }\n\n    pub fn is_java_lang_string(rf: Arc<Self>) -> bool {\n        let ptr = rf.get_raw_ptr();\n        unsafe {\n            match &(*ptr).v {\n                RefKind::Inst(inst) => {\n                    let cls = inst.class.get_class();\n                    cls.name.as_slice() == b\"java/lang/String\"\n                }\n                _ => false,\n            }\n        }\n    }\n\n    fn is_java_lang_string_eq(l: Arc<Self>, r: Arc<Self>) -> bool {\n        let offset = get_java_lang_string_value_offset();\n\n        //java.lang.String.value\n        let v1 = Class::get_field_value2(l, offset);\n        let v2 = Class::get_field_value2(r, offset);\n\n        let rf1 = v1.extract_ref();\n        let rf2 = v2.extract_ref();\n\n        let chars1 = rf1.extract_type_array().extract_chars();\n        let chars2 = rf2.extract_type_array().extract_chars();\n\n        chars1 == chars2\n    }\n}\n\nimpl OopPtr {\n    pub fn java_lang_string(rf: Arc<Self>) -> String {\n        let v = Self::java_lang_string_value(rf);\n        String::from_utf16_lossy(v.as_slice())\n    }\n\n    //java.lang.String.value\n    pub fn java_lang_string_value(rf: Arc<Self>) -> Vec<u16> {\n        let offset = get_java_lang_string_value_offset();\n        let v = Class::get_field_value2(rf, offset);\n        let rf = v.extract_ref();\n        let chars = rf.extract_type_array().extract_chars();\n        chars.to_vec()\n    }\n\n    pub fn java_lang_string_hash(rf: Arc<Self>) -> i32 {\n        let offset = get_java_lang_string_value_offset();\n        let v = Class::get_field_value2(rf, offset);\n\n        let rf = v.extract_ref();\n        let chars = rf.extract_type_array().extract_chars();\n\n        let mut h = 0i32;\n        for v in chars.iter() {\n            h = h.wrapping_mul(31).wrapping_add(*v as i32);\n        }\n\n        h\n    }\n\n    //java.lang.Integer.value\n    pub fn java_lang_integer_value(rf: Arc<Self>) -> i32 {\n        let offset = get_java_lang_integer_value_offset();\n        Class::get_field_value2(rf, offset).extract_int()\n    }\n\n    //java.lang.Thread.eetop\n    pub fn java_lang_thread_eetop(rf: Arc<Self>) -> i64 {\n        let fid = {\n            let inst = rf.extract_inst();\n            let cls = inst.class.clone();\n            let cls = cls.get_class();\n            cls.get_field_id(&new_br(\"eetop\"), &new_br(\"J\"), false)\n        };\n\n        Class::get_field_value(rf, fid).extract_long()\n    }\n}\n\nimpl Drop for OopPtr {\n    fn drop(&mut self) {\n        let _v = unsafe { Box::from_raw(self.0 as *mut RefKindDesc) };\n    }\n}\n\npub fn init() {\n    consts::init();\n}\n"
  },
  {
    "path": "crates/vm/src/oop/reference.rs",
    "content": "use crate::oop::{ArrayOopDesc, InstOopDesc, MirrorOopDesc, TypeArrayDesc};\nuse crate::runtime::thread::{Condvar, ReentrantMutex};\nuse std::fmt;\nuse std::fmt::Formatter;\nuse std::time::Duration;\n\n#[derive(Debug)]\npub enum RefKind {\n    Inst(InstOopDesc),\n    Array(ArrayOopDesc),\n    TypeArray(TypeArrayDesc),\n    Mirror(MirrorOopDesc),\n}\n\npub struct RefKindDesc {\n    pub v: RefKind,\n    pub hash_code: Option<i32>,\n\n    mutex: ReentrantMutex,\n    cond_var: Condvar,\n}\n\nimpl RefKindDesc {\n    pub fn new(v: RefKind) -> Self {\n        let mutex = unsafe {\n            let mut mutex = ReentrantMutex::uninitialized();\n            mutex.init();\n            mutex\n        };\n\n        let cond_var = unsafe {\n            let mut cond = Condvar::new();\n            cond.init();\n            cond\n        };\n\n        Self {\n            v,\n            hash_code: None,\n            mutex,\n            cond_var,\n        }\n    }\n}\n\nimpl RefKindDesc {\n    pub fn monitor_enter(&self) {\n        unsafe {\n            self.mutex.lock();\n        }\n    }\n\n    pub fn monitor_exit(&self) {\n        unsafe {\n            self.mutex.unlock();\n        }\n    }\n\n    pub fn wait(&self) {\n        unsafe {\n            self.cond_var.wait(&self.mutex);\n        }\n    }\n\n    pub fn wait_timeout(&self, duration: Duration) {\n        unsafe {\n            self.cond_var.wait_timeout(&self.mutex, duration);\n        }\n    }\n\n    pub fn notify_all(&self) {\n        unsafe {\n            self.cond_var.notify_all();\n        }\n    }\n}\n\nimpl RefKind {\n    pub fn extract_inst(&self) -> &InstOopDesc {\n        match &self {\n            RefKind::Inst(v) => v,\n            _ => unreachable!(),\n        }\n    }\n\n    pub fn extract_array(&self) -> &ArrayOopDesc {\n        match &self {\n            RefKind::Array(v) => v,\n            _ => unreachable!(),\n        }\n    }\n\n    pub fn extract_mut_array(&mut self) -> &mut ArrayOopDesc {\n        let v = self;\n        match v {\n            RefKind::Array(v) => v,\n            _ => unreachable!(),\n        }\n    }\n\n    pub fn extract_type_array(&self) -> &TypeArrayDesc {\n        match &self {\n            RefKind::TypeArray(v) => v,\n            _ => unreachable!(),\n        }\n    }\n\n    pub fn extract_mut_type_array(&mut self) -> &mut TypeArrayDesc {\n        let v = self;\n        match v {\n            RefKind::TypeArray(v) => v,\n            _ => unreachable!(),\n        }\n    }\n\n    pub fn extract_mirror(&self) -> &MirrorOopDesc {\n        match &self {\n            RefKind::Mirror(v) => v,\n            _ => unreachable!(),\n        }\n    }\n}\n\nimpl Drop for RefKindDesc {\n    fn drop(&mut self) {\n        unsafe {\n            self.mutex.destroy();\n        }\n    }\n}\n\nimpl fmt::Debug for RefKindDesc {\n    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"RefKindDesc\")\n            .field(\"v\", &self.v)\n            .field(\"hash_code\", &self.hash_code)\n            .field(\"mutex\", &\"mutex\")\n            .finish()\n    }\n}\n"
  },
  {
    "path": "crates/vm/src/oop/values.rs",
    "content": "use crate::runtime::ClassLoader;\n\n#[derive(Debug, Clone, Copy, PartialOrd, PartialEq)]\npub enum ValueType {\n    BYTE,\n    BOOLEAN,\n    CHAR,\n    SHORT,\n    INT,\n    LONG,\n    FLOAT,\n    DOUBLE,\n    VOID,\n    OBJECT,\n    ARRAY,\n}\n\nimpl From<&u8> for ValueType {\n    fn from(v: &u8) -> Self {\n        match v {\n            b'B' => ValueType::BYTE,\n            b'Z' => ValueType::BOOLEAN,\n            b'C' => ValueType::CHAR,\n            b'S' => ValueType::SHORT,\n            b'I' => ValueType::INT,\n            b'J' => ValueType::LONG,\n            b'F' => ValueType::FLOAT,\n            b'D' => ValueType::DOUBLE,\n            b'V' => ValueType::VOID,\n            b'L' => ValueType::OBJECT,\n            b'[' => ValueType::ARRAY,\n            t => {\n                let s = [*t];\n                let s = String::from_utf8_lossy(&s);\n                unreachable!(\"Unknown ValueType = {}\", s)\n            }\n        }\n    }\n}\n\nimpl Into<&[u8]> for ValueType {\n    fn into(self) -> &'static [u8] {\n        match self {\n            ValueType::BYTE => b\"B\",\n            ValueType::BOOLEAN => b\"Z\",\n            ValueType::CHAR => b\"C\",\n            ValueType::SHORT => b\"S\",\n            ValueType::INT => b\"I\",\n            ValueType::LONG => b\"J\",\n            ValueType::FLOAT => b\"F\",\n            ValueType::DOUBLE => b\"D\",\n            ValueType::VOID => b\"V\",\n            ValueType::OBJECT => b\"L\",\n            ValueType::ARRAY => b\"[\",\n        }\n    }\n}\n\nimpl ValueType {\n    pub fn parse_wrap(class_loader: Option<ClassLoader>, desc: &str) -> Self {\n        match desc.as_bytes().first().unwrap() {\n            b'B' | b'Z' | b'C' | b'S' | b'I' => ValueType::INT,\n            b'J' => ValueType::LONG,\n            b'F' => ValueType::FLOAT,\n            b'D' => ValueType::DOUBLE,\n            b'V' => ValueType::VOID,\n            b'L' => ValueType::OBJECT,\n            b'[' => ValueType::ARRAY,\n            _ => unreachable!(),\n        }\n    }\n\n    pub fn get_primitive_name(&self) -> &'static [u8] {\n        match *self {\n            ValueType::BYTE => b\"byte\",\n            ValueType::BOOLEAN => b\"boolean\",\n            ValueType::CHAR => b\"char\",\n            ValueType::SHORT => b\"short\",\n            ValueType::INT => b\"int\",\n            ValueType::LONG => b\"long\",\n            ValueType::FLOAT => b\"float\",\n            ValueType::DOUBLE => b\"double\",\n            ValueType::VOID | ValueType::OBJECT | ValueType::ARRAY => unreachable!(),\n        }\n    }\n}\n"
  },
  {
    "path": "crates/vm/src/runtime/class_loader.rs",
    "content": "use crate::native;\nuse crate::oop::class::ClassPtr;\nuse crate::oop::{self, Class, ValueType};\nuse crate::runtime::{self, ClassPathResult};\nuse crate::types::*;\nuse crate::util;\nuse class_parser::parse_class;\nuse classfile::{constant_pool, BytesRef, ConstantPool, U2};\nuse std::sync::{Arc, Mutex};\n\n#[derive(Debug, Copy, Clone)]\npub enum ClassLoader {\n    Base,\n    Bootstrap,\n}\n\npub fn require_class(class_loader: Option<ClassLoader>, name: &BytesRef) -> Option<ClassRef> {\n    require_class3(class_loader, name.as_slice())\n}\n\npub fn require_class2(index: U2, cp: &ConstantPool) -> Option<ClassRef> {\n    let class = constant_pool::get_class_name(cp, index as usize);\n    // trace!(\"require_class2 class = {}\", String::from_utf8_lossy(class.as_slice()));\n    require_class3(None, class.as_slice())\n}\n\npub fn require_class3(class_loader: Option<ClassLoader>, name: &[u8]) -> Option<ClassRef> {\n    let class_loader = class_loader.unwrap_or(ClassLoader::Bootstrap);\n    class_loader.load_class(name)\n}\n\nimpl ClassLoader {\n    fn load_class(&self, name: &[u8]) -> Option<ClassRef> {\n        debug_assert!(!name.contains(&b'.'));\n        //        error!(\"load_class name = {}\", String::from_utf8_lossy(name));\n        match self {\n            ClassLoader::Base => (),\n            ClassLoader::Bootstrap => {\n                let it = runtime::sys_dic_find(name);\n                if it.is_some() {\n                    //                    info!(\"load_class in dic: {}\", String::from_utf8_lossy(name));\n                    return it;\n                }\n            }\n        }\n\n        if is_array(name) {\n            self.load_array_class(name)\n        } else {\n            let class = self.load_class_from_path(name);\n            if let Some(class) = &class {\n                match self {\n                    ClassLoader::Base => (),\n                    ClassLoader::Bootstrap => {\n                        runtime::sys_dic_put(name, class.clone());\n                        let this_ref = class.clone();\n\n                        {\n                            let mut cls = class.get_mut_class();\n                            cls.set_class_state(oop::class::State::Loaded);\n                            cls.link_class(this_ref);\n                        }\n\n                        native::java_lang_Class::create_mirror(class.clone());\n                    }\n                }\n            }\n\n            class\n        }\n    }\n\n    fn load_array_class(&self, name: &[u8]) -> Option<ClassRef> {\n        match calc_dimension(name) {\n            Some(1) => {\n                // dimension == 1\n                match name.get(1) {\n                    Some(b'L') => {\n                        //[Ljava/lang/Object;\n                        let elm = &name[2..name.len() - 1];\n                        match self.load_class(elm) {\n                            Some(elm) => {\n                                let mut class = Class::new_object_ary(*self, elm, name);\n                                let class = ClassPtr::new(class);\n                                {\n                                    let this_ref = class.clone();\n                                    let mut class = class.get_mut_class();\n                                    class.link_class(this_ref);\n                                }\n                                match self {\n                                    ClassLoader::Base => (),\n                                    ClassLoader::Bootstrap => {\n                                        runtime::sys_dic_put(name, class.clone());\n                                    }\n                                }\n\n                                native::java_lang_Class::create_mirror(class.clone());\n\n                                Some(class)\n                            }\n                            None => None,\n                        }\n                    }\n\n                    Some(t) => {\n                        //B, Z...\n                        let elm = t.into();\n                        let class = Class::new_prime_ary(*self, elm);\n                        let class = ClassPtr::new(class);\n\n                        {\n                            let this_ref = class.clone();\n                            let mut class = class.get_mut_class();\n                            class.link_class(this_ref);\n                        }\n\n                        match self {\n                            ClassLoader::Base => (),\n                            ClassLoader::Bootstrap => {\n                                runtime::sys_dic_put(name, class.clone());\n                            }\n                        }\n\n                        //mirror has been created when vm inited\n\n                        Some(class)\n                    }\n\n                    None => unreachable!(),\n                }\n            }\n\n            _ => {\n                // dimension > 1\n                let down_type_name = &name[1..];\n                match self.load_array_class(down_type_name) {\n                    Some(down_type) => {\n                        let class = Class::new_wrapped_ary(*self, down_type);\n                        let class = ClassPtr::new(class);\n                        match self {\n                            ClassLoader::Base => (),\n                            ClassLoader::Bootstrap => {\n                                runtime::sys_dic_put(name, class.clone());\n                            }\n                        }\n\n                        native::java_lang_Class::create_mirror(class.clone());\n\n                        Some(class)\n                    }\n\n                    None => None,\n                }\n            }\n        }\n    }\n\n    fn load_class_from_path(&self, name: &[u8]) -> Option<ClassRef> {\n        let name = unsafe { std::str::from_utf8_unchecked(name) };\n        match runtime::find_class_in_classpath(name) {\n            Ok(ClassPathResult(_, buf)) => match parse_class(&buf) {\n                Ok(cf) => {\n                    let cfr = Arc::new(Box::new(cf.1));\n                    let class = Class::new_class(cfr, Some(*self));\n                    Some(ClassPtr::new(class))\n                }\n\n                Err(e) => unreachable!(\"name={}, {}\", name, e),\n            },\n\n            Err(_) => None,\n        }\n    }\n}\n\nfn calc_dimension(name: &[u8]) -> Option<usize> {\n    if is_array(name) {\n        name.iter().position(|&c| c != b'[')\n    } else {\n        None\n    }\n}\n\nfn is_array(name: &[u8]) -> bool {\n    name.starts_with(&[b'['])\n}\n\n#[cfg(test)]\nmod tests {\n    #[test]\n    fn t_basic() {\n        use super::calc_dimension;\n        assert_eq!(calc_dimension(\"\".as_bytes()), None);\n        assert_eq!(calc_dimension(\"Ljava/lang/Object;\".as_bytes()), None);\n        assert_eq!(calc_dimension(\"Z\".as_bytes()), None);\n        assert_eq!(calc_dimension(\"[B\".as_bytes()), Some(1));\n        assert_eq!(calc_dimension(\"[[B\".as_bytes()), Some(2));\n        assert_eq!(calc_dimension(\"[[[B\".as_bytes()), Some(3));\n        assert_eq!(calc_dimension(\"[[[[B\".as_bytes()), Some(4));\n        assert_eq!(calc_dimension(\"[[[[[B\".as_bytes()), Some(5));\n        assert_eq!(calc_dimension(\"[Ljava/lang/Object;\".as_bytes()), Some(1));\n        assert_eq!(calc_dimension(\"[[Ljava/lang/Object;\".as_bytes()), Some(2));\n\n        let name = \"[Ljava/lang/Object;\";\n        assert_eq!(\"java/lang/Object\", &name[2..name.len() - 1]);\n    }\n}\n"
  },
  {
    "path": "crates/vm/src/runtime/class_path_manager.rs",
    "content": "use crate::util;\nuse std::fs::File;\nuse std::io::{self, BufReader, Cursor, Read, Seek};\nuse std::path::{self, Path};\nuse std::sync::{Arc, Mutex, RwLock};\nuse zip::ZipArchive;\n\nlazy_static! {\n    static ref CPM: RwLock<ClassPathManager> = { RwLock::new(ClassPathManager::new()) };\n}\n\npub fn init() {\n    lazy_static::initialize(&CPM);\n}\n\npub fn find_class(name: &str) -> Result<ClassPathResult, io::Error> {\n    let cpm = CPM.read().unwrap();\n    cpm.search_class(name)\n}\n\npub fn add_path(path: &str) {\n    let mut cpm = CPM.write().unwrap();\n    cpm.add_class_path(path);\n}\n\npub fn add_paths(path: &str) {\n    let mut cpm = CPM.write().unwrap();\n    cpm.add_class_paths(path);\n}\n\n#[derive(Debug)]\npub struct ClassPathResult(pub String, pub Vec<u8>);\n\ntype ZipRef = Arc<Mutex<Box<ZipArchive<File>>>>;\n\nenum ClassSource {\n    DIR,\n    JAR(ZipRef),\n}\n\nstruct ClassPathEntry(ClassSource, String);\n\nstruct ClassPathManager {\n    runtime_class_path: Vec<ClassPathEntry>,\n}\n\nimpl ClassPathManager {\n    fn new() -> Self {\n        Self {\n            runtime_class_path: vec![],\n        }\n    }\n\n    pub fn add_class_path(&mut self, path: &str) -> Result<(), io::Error> {\n        let p = Path::new(path);\n        if p.is_dir() {\n            self.runtime_class_path\n                .push(ClassPathEntry(ClassSource::DIR, path.to_string()));\n        } else {\n            let f = File::open(p)?;\n            let mut z = ZipArchive::new(f)?;\n            let handle = Arc::new(Mutex::new(Box::new(z)));\n            self.runtime_class_path\n                .push(ClassPathEntry(ClassSource::JAR(handle), path.to_string()));\n        }\n\n        Ok(())\n    }\n\n    pub fn add_class_paths(&mut self, path: &str) {\n        path.split(util::PATH_SEP).for_each(|p| {\n            if let Err(e) = self.add_class_path(p) {\n                error!(\"add class path error, path={}, e={:?}\", p, e)\n            }\n        });\n    }\n\n    pub fn search_class(&self, name: &str) -> Result<ClassPathResult, io::Error> {\n        let name = name.replace(\"/\", util::FILE_SEP);\n        let name = name.replace(\".\", util::FILE_SEP);\n\n        trace!(\"search_class: {}\", name);\n\n        for it in self.runtime_class_path.iter() {\n            match &it.0 {\n                ClassSource::DIR => {\n                    let mut p = String::from(&it.1);\n                    p.push_str(util::FILE_SEP);\n                    p.push_str(&name);\n                    p.push_str(\".class\");\n                    if let Ok(data) = std::fs::read(&p) {\n                        return Ok(ClassPathResult(p, data));\n                    }\n                }\n\n                ClassSource::JAR(handle) => {\n                    let mut p = String::from(&name);\n                    p.push_str(\".class\");\n\n                    let mut handle = handle.lock().unwrap();\n                    let mut zf = handle.by_name(&p);\n\n                    if let Ok(mut zf) = zf {\n                        let mut v = Vec::with_capacity(zf.size() as usize);\n                        let r = zf.read_to_end(&mut v);\n                        debug_assert!(r.is_ok());\n                        return Ok(ClassPathResult(it.1.clone(), v));\n                    }\n                }\n            }\n        }\n\n        Err(io::Error::new(\n            io::ErrorKind::NotFound,\n            format!(\"Search class failed: {}\", name),\n        ))\n    }\n\n    pub fn size(&self) -> usize {\n        self.runtime_class_path.len()\n    }\n}\n\n#[cfg(test)]\nmod tests {\n\n    #[test]\n    fn t_basic_zip() {\n        let f = \"test/class_path_test.jar\";\n        let f = super::File::open(f).unwrap();\n        let mut za = super::ZipArchive::new(f).unwrap();\n\n        for i in 0..za.len() {\n            let mut zf = za.by_index(i).unwrap();\n            println!(\"{}\", zf.name());\n        }\n    }\n\n    #[test]\n    fn t_replace_all() {\n        let class = \"java.lang.String\";\n        assert_eq!(class.replace(\".\", \"/\"), \"java/lang/String\");\n    }\n\n    #[test]\n    fn t_add_cls_path() {\n        let mut cpm = super::ClassPathManager::new();\n        assert!(cpm.add_class_path(\"test/\").is_ok());\n        assert!(cpm.add_class_path(\"test_no_exist/\").is_err());\n        assert!(cpm\n            .add_class_path(\"test/classloader/class_path_test.jar\")\n            .is_ok());\n        assert!(cpm\n            .add_class_path(\"test/classloader/class_path_test_no_exist.jar\")\n            .is_err());\n    }\n\n    #[test]\n    fn t_add_cls_paths() {\n        let mut cpm = super::ClassPathManager::new();\n        cpm.add_class_paths(\"test/:test/classloader/class_path_test.jar\");\n        assert_eq!(2, cpm.size());\n    }\n\n    #[test]\n    fn t_search_cls() {\n        let mut cpm = super::ClassPathManager::new();\n        let _ = cpm.add_class_path(\"test/classloader/class_path_test.jar\");\n        assert!(cpm.search_class(\"Foo\").is_ok());\n    }\n\n    #[test]\n    fn t_search_cls2() {\n        let mut cpm = super::ClassPathManager::new();\n        cpm.add_class_paths(\"test/classloader/class_path_test.jar\");\n        assert!(cpm.search_class(\"Sample\").is_err());\n        assert!(cpm.search_class(\"Foo\").is_ok());\n    }\n}\n"
  },
  {
    "path": "crates/vm/src/runtime/cmp.rs",
    "content": "use crate::oop;\nuse crate::runtime::require_class3;\nuse crate::types::ClassRef;\nuse classfile::consts as cls_consts;\nuse std::sync::Arc;\n\npub fn instance_of(s: ClassRef, t: ClassRef) -> bool {\n    // Return if S and T are the same class\n    if Arc::ptr_eq(&s, &t) {\n        return true;\n    }\n\n    let (s_kind, s_is_intf) = {\n        let cls = s.get_class();\n        (cls.get_class_kind_type(), cls.is_interface())\n    };\n\n    let (t_kind, t_is_intf) = {\n        let cls = t.get_class();\n        (cls.get_class_kind_type(), cls.is_interface())\n    };\n\n    // If S is an ordinary (non-array) class\n    if s_kind == oop::class::ClassKindType::Instance && !s_is_intf {\n        // If T is an interface type, then S must implement interface T.\n        if t_is_intf {\n            let s = s.get_class();\n            return s.check_interface(t);\n        }\n\n        // If T is a class type, then S must be the same class as T,\n        // or S must be a subclass of T;\n        if t_kind == oop::class::ClassKindType::Instance {\n            return check_inherit(s, t);\n        }\n\n        return false;\n    }\n\n    // If S is an interface type\n    if s_is_intf {\n        // If T is an interface type, then T must be the same interface as S\n        // or a superinterface of S.\n        if t_is_intf {\n            return check_inherit(s, t);\n        }\n\n        // If T is a class type, then T must be Object\n        if t_kind == oop::class::ClassKindType::Instance {\n            let object = require_class3(None, cls_consts::J_OBJECT).unwrap();\n            return Arc::ptr_eq(&t, &object);\n        }\n\n        return false;\n    }\n\n    // If S is a class representing the array type SC[],\n    // that is, an array of components of type SC\n    match s_kind {\n        oop::class::ClassKindType::TypAry | oop::class::ClassKindType::ObjectAry => {\n            // If T is an interface type, then T must be one of the interfaces\n            // implemented by arrays (JLS §4.10.3).\n            // https://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.10.3\n            // array implements:\n            // 1. java/lang/Cloneable\n            // 2. java/io/Serializable\n            if t_is_intf {\n                let serializable = require_class3(None, cls_consts::J_SERIALIZABLE).unwrap();\n                let cloneable = require_class3(None, cls_consts::J_CLONEABLE).unwrap();\n                return Arc::ptr_eq(&t, &serializable) || Arc::ptr_eq(&t, &cloneable);\n            }\n\n            if t_kind == oop::class::ClassKindType::Instance {\n                let object = require_class3(None, cls_consts::J_OBJECT).unwrap();\n                return Arc::ptr_eq(&t, &object);\n            }\n\n            if t_kind == oop::class::ClassKindType::TypAry\n                && s_kind == oop::class::ClassKindType::TypAry\n            {\n                let cls = s.get_class();\n                let (s_dimension, s_value_type) = match &cls.kind {\n                    oop::class::ClassKind::TypeArray(cls) => (cls.get_dimension(), cls.value_type),\n                    _ => unreachable!(),\n                };\n\n                let cls = t.get_class();\n                let (t_dimension, t_value_type) = match &cls.kind {\n                    oop::class::ClassKind::TypeArray(cls) => (cls.get_dimension(), cls.value_type),\n                    _ => unreachable!(),\n                };\n                return s_dimension == t_dimension && s_value_type == t_value_type;\n            }\n\n            if t_kind == oop::class::ClassKindType::ObjectAry\n                && s_kind == oop::class::ClassKindType::ObjectAry\n            {\n                let cls = s.get_class();\n                let (s_dimension, s_component) = match &cls.kind {\n                    oop::class::ClassKind::ObjectArray(cls) => {\n                        (cls.get_dimension(), cls.component.clone().unwrap())\n                    }\n                    _ => unreachable!(),\n                };\n                let cls = t.get_class();\n                let (t_dimension, t_component) = match &cls.kind {\n                    oop::class::ClassKind::ObjectArray(cls) => {\n                        (cls.get_dimension(), cls.component.clone().unwrap())\n                    }\n                    _ => unreachable!(),\n                };\n                return s_dimension == t_dimension && check_inherit(s_component, t_component);\n            }\n        }\n        _ => (),\n    }\n\n    false\n}\n\npub fn check_inherit(s: ClassRef, t: ClassRef) -> bool {\n    let mut super_cls = s;\n\n    loop {\n        if Arc::ptr_eq(&super_cls, &t) {\n            return true;\n        }\n\n        let cls = { super_cls.get_class().super_class.clone() };\n        match cls {\n            Some(cls) => super_cls = cls,\n            None => break,\n        }\n    }\n\n    false\n}\n"
  },
  {
    "path": "crates/vm/src/runtime/constant_pool.rs",
    "content": "use std::cell::RefCell;\n\nuse rustc_hash::FxHashMap;\n\nuse classfile::ConstantPool;\n\nuse crate::oop::field;\nuse crate::types::{FieldIdRef, MethodIdRef};\nuse crate::{oop, runtime};\n\nenum CacheType {\n    Field(FieldIdRef),\n    Method(MethodIdRef),\n}\n\nimpl CacheType {\n    fn extract_field(&self) -> FieldIdRef {\n        match self {\n            CacheType::Field(fid) => fid.clone(),\n            _ => unreachable!(),\n        }\n    }\n\n    fn extract_method(&self) -> MethodIdRef {\n        match self {\n            CacheType::Method(mid) => mid.clone(),\n            _ => unreachable!(),\n        }\n    }\n}\n\npub struct ConstantPoolCache {\n    cp: ConstantPool,\n    cache: RefCell<FxHashMap<usize, CacheType>>,\n}\n\nimpl ConstantPoolCache {\n    pub fn new(cp: ConstantPool) -> Self {\n        Self {\n            cp,\n            cache: RefCell::new(FxHashMap::default()),\n        }\n    }\n\n    pub fn get_field(&self, idx: usize, is_static: bool) -> FieldIdRef {\n        let cache = self.cache.borrow();\n        let it = cache.get(&idx);\n        match it {\n            Some(it) => it.extract_field(),\n            None => {\n                drop(cache);\n                let fid = field::get_field_ref(&self.cp, idx, is_static);\n                self.cache_field(idx, fid.clone());\n                fid\n            }\n        }\n    }\n\n    fn cache_field(&self, k: usize, v: FieldIdRef) {\n        let mut cache = self.cache.borrow_mut();\n        let v = CacheType::Field(v);\n        cache.insert(k, v);\n    }\n\n    pub fn get_method(&self, idx: usize) -> MethodIdRef {\n        let cache = self.cache.borrow();\n        let it = cache.get(&idx);\n        match it {\n            Some(it) => it.extract_method(),\n            None => {\n                drop(cache);\n                let m = runtime::method::get_method_ref(&self.cp, idx).unwrap();\n                self.cache_method(idx, m.clone());\n                m\n            }\n        }\n    }\n\n    fn cache_method(&self, k: usize, v: MethodIdRef) {\n        let mut cache = self.cache.borrow_mut();\n        let v = CacheType::Method(v);\n        cache.insert(k, v);\n    }\n}\n"
  },
  {
    "path": "crates/vm/src/runtime/consts.rs",
    "content": "pub const THREAD_MAX_STACK_FRAMES: usize = 512;\n// pub const WARN_THREAD_MAX_STACK_FRAMES: usize = 512;\n"
  },
  {
    "path": "crates/vm/src/runtime/dataarea.rs",
    "content": "use crate::oop::Oop;\nuse crate::runtime::local::Local;\nuse crate::runtime::stack::Stack;\nuse std::cell::RefCell;\nuse std::sync::{Arc, RwLock};\n\n/*\nThe origin of DataArea\n\njava method execution method:\nEvery time a method is called, a new Frame is constructed,\nand the frame is pushed to the current thread.frames stack.\nAfter the method is executed, the Frame is popped.\nIf an exception occurs, jvm_fillInStackTrace traverses the current thread frames:\nextract the class name, method name, and pc (pc for LineNumberTable Attributes from each frame)\nLocate the error line of code) and construct an exception stack.\n\nThe DataArea in the Frame is wrapped with RefCell, so that java_call::invoke_java can execute Java\nMethod, you can use the read-only frame to execute bytecode; when there is an exception, you can also let\njvm_fillInStackTrace traverse the frames to get the necessary information.\nThe nature of RefCell makes this possible.\nIn a read-only Frame context, to modify the DataArea, borrow_mut is fine.\n*/\npub struct DataArea {\n    pub stack: RefCell<Stack>,\n    pub return_v: RefCell<Option<Oop>>,\n}\n\nunsafe impl Sync for DataArea {}\n\nimpl DataArea {\n    pub fn new(max_stack: usize) -> Self {\n        let stack = RefCell::new(Stack::new(max_stack));\n\n        Self {\n            stack,\n            return_v: RefCell::new(None),\n        }\n    }\n}\n"
  },
  {
    "path": "crates/vm/src/runtime/exception.rs",
    "content": "use crate::oop::{self, Oop};\nuse crate::runtime::{self, require_class3};\nuse crate::types::JavaThreadRef;\nuse crate::{new_br, util};\nuse std::sync::atomic::Ordering;\n\npub fn new(name: &[u8], msg: Option<String>) -> Oop {\n    let cls = match require_class3(None, name) {\n        Some(cls) => cls,\n        None => panic!(\"ClassNotFound: {}\", String::from_utf8_lossy(name)),\n    };\n\n    oop::class::init_class(&cls);\n    oop::class::init_class_fully(&cls);\n\n    let ex = Oop::new_inst(cls.clone());\n\n    //invoke ctor\n    match &msg {\n        Some(msg) => {\n            //with 'String' arg ctor\n            let msg = util::oop::new_java_lang_string2(msg);\n            let args = vec![ex.clone(), msg];\n            runtime::invoke::invoke_ctor(cls, new_br(\"(Ljava/lang/String;)V\"), args);\n        }\n        None => {\n            //No arg ctor\n            let args = vec![ex.clone()];\n            runtime::invoke::invoke_ctor(cls, new_br(\"()V\"), args);\n        }\n    }\n\n    ex\n}\n\npub fn meet_ex(cls_name: &'static [u8], msg: Option<String>) {\n    let jt = runtime::thread::current_java_thread();\n    {\n        let jt = jt.read().unwrap();\n        let frame = jt.frames.last().unwrap();\n        let frame = frame.try_read().unwrap();\n        frame.ex_here.store(true, Ordering::Relaxed);\n    }\n\n    let ex = new(cls_name, msg);\n    jt.write().unwrap().set_ex(ex);\n}\n"
  },
  {
    "path": "crates/vm/src/runtime/frame.rs",
    "content": "use crate::oop;\nuse crate::runtime::DataArea;\nuse crate::types::*;\nuse classfile::{ConstantPool, U1};\nuse std::sync::Arc;\n\npub struct Frame {\n    pub frame_id: usize, //for debug\n    pub class: ClassRef,\n    //avoid lock class to access cp\n    pub cp: ConstantPool,\n    pub mir: MethodIdRef,\n    pub code: Arc<Vec<U1>>,\n\n    pub pc: std::sync::atomic::AtomicI32,\n    pub ex_here: std::sync::atomic::AtomicBool,\n\n    // The variable part of Frame is placed here\n    pub area: DataArea,\n}\n\n// unsafe impl Sync for Frame {}\n\n//new\nimpl Frame {\n    pub fn new(mir: MethodIdRef, frame_id: usize) -> Self {\n        let class = mir.method.class.clone();\n        let cp = {\n            let cls_obj = class.extract_inst();\n            cls_obj.class_file.cp.clone()\n        };\n        let pc = std::sync::atomic::AtomicI32::new(0);\n        let ex_here = std::sync::atomic::AtomicBool::new(false);\n\n        // trace!(\"method.code.is_some = {}\", mir.method.code.is_some());\n        match &mir.method.code {\n            Some(code) => {\n                // trace!(\"max_locals = {}, max_stack = {}\", code.max_locals, code.max_stack);\n                let area = DataArea::new(code.max_stack as usize);\n                let code = code.code.clone();\n\n                Self {\n                    frame_id,\n                    class,\n                    cp,\n                    mir,\n                    code,\n                    pc,\n                    ex_here,\n                    area,\n                }\n            }\n\n            None => Self {\n                frame_id,\n                class,\n                cp: Arc::new(Vec::new()),\n                mir,\n                code: Arc::new(vec![]),\n                pc,\n                ex_here,\n                area: DataArea::new(0),\n            },\n        }\n    }\n}\n"
  },
  {
    "path": "crates/vm/src/runtime/init_vm.rs",
    "content": "use crate::oop;\nuse crate::oop::{Class, Oop};\nuse crate::runtime::{self, require_class3};\nuse crate::types::JavaThreadRef;\nuse crate::util;\nuse crate::{native, new_br};\nuse classfile::consts::{\n    J_ARRAY_INDEX_OUT_OF_BOUNDS, J_CLASS, J_CLASS_NOT_FOUND, J_CLONEABLE, J_FIELD, J_INPUT_STREAM,\n    J_INTERNAL_ERROR, J_IOEXCEPTION, J_METHOD_CTOR, J_NPE, J_OBJECT, J_PRINT_STREAM,\n    J_SECURITY_MANAGER, J_SERIALIZABLE, J_STRING, J_SYSTEM, J_THREAD, J_THREAD_GROUP, J_THROWABLE,\n};\nuse std::borrow::BorrowMut;\nuse std::sync::Arc;\n\npub fn initialize_jvm() {\n    initialize_vm_structs();\n\n    let thread_cls = oop::class::load_and_init(J_THREAD);\n    let thread_group_cls = oop::class::load_and_init(J_THREAD_GROUP);\n\n    let init_thread_oop = oop::Oop::new_inst(thread_cls.clone());\n    {\n        let mut cls = thread_cls.get_mut_class();\n        //todo: getNativeHandler\n        //        let id = util::new_field_id(J_THREAD, b\"eetop\", b\"J\");\n        //        cls.put_field_value2(init_thread_oop.clone(), id, oop::OopDesc::new_long(0));\n        //todo: define java::lang::ThreadPriority::NORMAL_PRIORITY\n        let id = cls.get_field_id(&new_br(\"priority\"), &new_br(\"I\"), false);\n        Class::put_field_value(init_thread_oop.extract_ref(), id, oop::Oop::new_int(5));\n    }\n\n    // JavaMainThread is created with java_thread_obj none\n    // Now we have created a thread for it.\n    let jt = runtime::thread::current_java_thread();\n    jt.write()\n        .unwrap()\n        .set_java_thread_obj(init_thread_oop.clone());\n\n    // Create and construct the system thread group.\n    let system_thread_group = oop::Oop::new_inst(thread_group_cls.clone());\n    let args = vec![system_thread_group.clone()];\n    runtime::invoke::invoke_ctor(thread_group_cls.clone(), new_br(\"()V\"), args);\n\n    let main_thread_group = oop::Oop::new_inst(thread_group_cls.clone());\n\n    {\n        let mut cls = thread_cls.get_mut_class();\n        let id = cls.get_field_id(&new_br(\"group\"), &new_br(\"Ljava/lang/ThreadGroup;\"), false);\n        Class::put_field_value(init_thread_oop.extract_ref(), id, main_thread_group.clone());\n    }\n\n    let _ = oop::class::load_and_init(J_INPUT_STREAM);\n    let _ = oop::class::load_and_init(J_PRINT_STREAM);\n    let _ = oop::class::load_and_init(J_SECURITY_MANAGER);\n\n    // Construct the main thread group\n    let args = vec![\n        main_thread_group.clone(),\n        Oop::Null,\n        system_thread_group,\n        util::oop::new_java_lang_string2(\"main\"),\n    ];\n    runtime::invoke::invoke_ctor(\n        thread_group_cls,\n        new_br(\"(Ljava/lang/Void;Ljava/lang/ThreadGroup;Ljava/lang/String;)V\"),\n        args,\n    );\n\n    //todo: disable sun.security.util.Debug for the following operations\n    //need to impl java_security_accesscontroller\n    //    let sun_debug_cls = do_init(b\"sun/security/util/Debug\", jt);\n\n    let args = vec![\n        init_thread_oop,\n        main_thread_group,\n        util::oop::new_java_lang_string2(\"main\"),\n    ];\n    runtime::invoke::invoke_ctor(\n        thread_cls,\n        new_br(\"(Ljava/lang/ThreadGroup;Ljava/lang/String;)V\"),\n        args,\n    );\n\n    hack_classes();\n\n    let init_system_classes_method = {\n        let cls = require_class3(None, J_SYSTEM).unwrap();\n        let cls = cls.get_class();\n        cls.get_static_method(&new_br(\"initializeSystemClass\"), &new_br(\"()V\"))\n            .unwrap()\n    };\n    let mut jc = runtime::invoke::JavaCall::new_with_args(init_system_classes_method, vec![]);\n    jc.invoke(None, false);\n\n    //todo: re-enable sun.security.util.Debug\n\n    //setup security\n    let _ = oop::class::load_and_init(b\"sun/security/provider/Sun\");\n    let _ = oop::class::load_and_init(b\"sun/security/rsa/SunRsaSign\");\n    let _ = oop::class::load_and_init(b\"com/sun/net/ssl/internal/ssl/Provider\");\n}\n\nfn initialize_vm_structs() {\n    let class_obj = oop::class::load_and_init(J_CLASS);\n    native::java_lang_Class::create_delayed_mirrors();\n    native::java_lang_Class::create_delayed_ary_mirrors();\n\n    let _ = oop::class::load_and_init(J_OBJECT);\n    let string_cls = oop::class::load_and_init(J_STRING);\n    {\n        let cls = string_cls.get_class();\n        let fir = cls.get_field_id(&new_br(\"value\"), &new_br(\"[C\"), false);\n        util::oop::set_java_lang_string_value_offset(fir.offset);\n    }\n\n    let integer_cls = oop::class::load_and_init(b\"java/lang/Integer\");\n    {\n        let cls = integer_cls.get_class();\n        let fir = cls.get_field_id(&new_br(\"value\"), &new_br(\"I\"), false);\n        util::oop::set_java_lang_integer_value_offset(fir.offset);\n    }\n\n    let _ = oop::class::load_and_init(J_CLONEABLE);\n    let _ = oop::class::load_and_init(J_SERIALIZABLE);\n    let _ = oop::class::load_and_init(J_NPE);\n    let _ = oop::class::load_and_init(J_ARRAY_INDEX_OUT_OF_BOUNDS);\n    let _ = oop::class::load_and_init(J_CLASS_NOT_FOUND);\n    let _ = oop::class::load_and_init(J_INTERNAL_ERROR);\n    let _ = oop::class::load_and_init(J_IOEXCEPTION);\n    let _ = oop::class::load_and_init(J_FIELD);\n    let _ = oop::class::load_and_init(J_METHOD_CTOR);\n    let _ = oop::class::load_and_init(J_THROWABLE);\n\n    //todo:\n    //java::lang::reflect::Constructor::initialize\n    //java::lang::reflect::Method::initialize\n\n    {\n        let mut cls = class_obj.get_mut_class();\n        let id = cls.get_field_id(&new_br(\"useCaches\"), &new_br(\"Z\"), true);\n        cls.put_static_field_value(id, oop::Oop::new_int(1));\n    }\n}\n\nfn hack_classes() {\n    let charset_cls = oop::class::load_and_init(b\"java/nio/charset/Charset\");\n    let ascii_charset_cls = oop::class::load_and_init(b\"sun/nio/cs/US_ASCII\");\n\n    let ascii_inst = oop::Oop::new_inst(ascii_charset_cls.clone());\n    let args = vec![ascii_inst.clone()];\n    runtime::invoke::invoke_ctor(ascii_charset_cls, new_br(\"()V\"), args);\n\n    {\n        let mut cls = charset_cls.get_mut_class();\n        let id = cls.get_field_id(\n            &new_br(\"defaultCharset\"),\n            &new_br(\"Ljava/nio/charset/Charset;\"),\n            true,\n        );\n        cls.put_static_field_value(id, ascii_inst);\n    }\n\n    let encoder = oop::class::load_and_init(b\"sun/nio/cs/StreamEncoder\");\n    {\n        let mut cls = encoder.get_mut_class();\n        cls.hack_as_native(b\"forOutputStreamWriter\", b\"(Ljava/io/OutputStream;Ljava/lang/Object;Ljava/lang/String;)Lsun/nio/cs/StreamEncoder;\");\n    }\n\n    let system = oop::class::load_and_init(b\"java/lang/System\");\n\n    {\n        let mut cls = system.get_mut_class();\n        cls.hack_as_native(b\"load\", b\"(Ljava/lang/String;)V\");\n\n        //todo: support load lib\n        cls.hack_as_native(b\"loadLibrary\", b\"(Ljava/lang/String;)V\");\n\n        //fixme: rm, just for debug\n        //        let id = util::new_method_id(b\"getProperty\", b\"(Ljava/lang/String;)Ljava/lang/String;\");\n        //        cls.hack_as_native(id);\n    }\n\n    /*\n    let mut mir = {\n        let cls = encoder.lock().unwrap();\n        let id = util::new_method_id(b\"forOutputStreamWriter\", b\"(Ljava/io/OutputStream;Ljava/lang/Object;Ljava/lang/String;)Lsun/nio/cs/StreamEncoder;\");\n        cls.get_static_method(id).unwrap()\n    };\n    */\n}\n"
  },
  {
    "path": "crates/vm/src/runtime/interp.rs",
    "content": "use crate::oop::{\n    self, consts as oop_consts, field, Class, ClassKind, Oop, OopPtr, TypeArrayDesc, ValueType,\n};\nuse crate::runtime::local::Local;\nuse crate::runtime::stack::Stack;\nuse crate::runtime::{\n    self, cmp, exception, require_class, require_class2, require_class3, thread, DataArea, Frame,\n    JavaCall,\n};\nuse crate::types::*;\nuse crate::util;\nuse classfile::{\n    constant_pool::get_utf8 as get_cp_utf8, consts as cls_const, ClassFile, ConstantPool,\n    ConstantPoolType, OpCode, U1, U2,\n};\nuse nix::sys::socket::SockType::Datagram;\nuse std::borrow::BorrowMut;\nuse std::cell::RefCell;\nuse std::collections::HashMap;\nuse std::ops::Deref;\nuse std::sync::atomic::{AtomicBool, Ordering};\nuse std::sync::{Arc, RwLockReadGuard};\n\nmacro_rules! array_store {\n    ($ary:ident, $pos:ident, $v:ident) => {\n        let len = $ary.len();\n        if ($pos < 0) || ($pos as usize >= len) {\n            let msg = format!(\"length is {}, but index is {}\", len, $pos);\n            exception::meet_ex(cls_const::J_ARRAY_INDEX_OUT_OF_BOUNDS, Some(msg));\n        } else {\n            $ary[$pos as usize] = $v;\n        }\n    };\n}\n\nmacro_rules! iarray_load {\n    ($area:ident, $ary:ident, $pos:ident) => {\n        let len = $ary.len();\n        if ($pos < 0) || ($pos as usize >= len) {\n            drop($area);\n            let msg = format!(\"length is {}, but index is {}\", len, $pos);\n            exception::meet_ex(cls_const::J_ARRAY_INDEX_OUT_OF_BOUNDS, Some(msg));\n        } else {\n            $area.push_int($ary[$pos as usize] as i32);\n        }\n    };\n}\n\nmacro_rules! read_byte {\n    ($pc:expr, $code:expr) => {{\n        let pc = $pc.fetch_add(1, Ordering::Relaxed);\n        $code[pc as usize]\n    }};\n}\n\nmacro_rules! read_i2 {\n    ($pc:expr, $code:expr) => {{\n        let h = read_byte!($pc, $code) as i16;\n        let l = read_byte!($pc, $code) as i16;\n        (h << 8 | l) as i32\n    }};\n}\n\nmacro_rules! read_u1 {\n    ($pc:expr, $code:expr) => {{\n        let pc = $pc.fetch_add(1, Ordering::Relaxed);\n        $code[pc as usize] as usize\n    }};\n}\n\nmacro_rules! read_u2 {\n    ($pc:expr, $code:expr) => {{\n        read_u1!($pc, $code) << 8 | read_u1!($pc, $code)\n    }};\n}\n\nmacro_rules! opcode_const {\n    (null, $interp:ident) => {\n        let mut stack = $interp.frame.area.stack.borrow_mut();\n        stack.push_null();\n    };\n    (m1, $interp:ident) => {\n        let mut stack = $interp.frame.area.stack.borrow_mut();\n        stack.push_const_m1();\n    };\n    (0, $interp:ident, $with_nop:expr) => {\n        let mut stack = $interp.frame.area.stack.borrow_mut();\n        stack.push_const0($with_nop);\n    };\n    (1, $interp:ident, $with_nop:expr) => {\n        let mut stack = $interp.frame.area.stack.borrow_mut();\n        stack.push_const1($with_nop);\n    };\n    (2, $interp:ident) => {\n        let mut stack = $interp.frame.area.stack.borrow_mut();\n        stack.push_const2();\n    };\n    (3, $interp:ident) => {\n        let mut stack = $interp.frame.area.stack.borrow_mut();\n        stack.push_const3();\n    };\n    (4, $interp:ident) => {\n        let mut stack = $interp.frame.area.stack.borrow_mut();\n        stack.push_const4();\n    };\n    (5, $interp:ident) => {\n        let mut stack = $interp.frame.area.stack.borrow_mut();\n        stack.push_const5();\n    };\n}\n\nmacro_rules! opcode_load {\n    (int, $interp:ident, $pos:expr) => {\n        let v = $interp.local.get_int($pos);\n        let mut stack = $interp.frame.area.stack.borrow_mut();\n        stack.push_int(v);\n    };\n    (long, $interp:ident, $pos:expr) => {\n        let v = $interp.local.get_long($pos);\n        let mut stack = $interp.frame.area.stack.borrow_mut();\n        stack.push_long(v);\n    };\n    (float, $interp:ident, $pos:expr) => {\n        let v = $interp.local.get_float($pos);\n        let mut stack = $interp.frame.area.stack.borrow_mut();\n        stack.push_float(v);\n    };\n    (double, $interp:ident, $pos:expr) => {\n        let v = $interp.local.get_double($pos);\n        let mut stack = $interp.frame.area.stack.borrow_mut();\n        stack.push_double(v);\n    };\n    (a, $interp:ident, $pos:expr) => {\n        let v = $interp.local.get_ref($pos);\n        let mut stack = $interp.frame.area.stack.borrow_mut();\n        stack.push_ref(v, false);\n    };\n}\n\nmacro_rules! opcode_store {\n    (int, $interp:ident, $pos:expr) => {\n        let mut stack = $interp.frame.area.stack.borrow_mut();\n        let v = stack.pop_int();\n        $interp.local.set_int($pos, v);\n    };\n    (long, $interp:ident, $pos:expr) => {\n        let mut stack = $interp.frame.area.stack.borrow_mut();\n        let v = stack.pop_long();\n        $interp.local.set_long($pos, v);\n    };\n    (float, $interp:ident, $pos:expr) => {\n        let mut stack = $interp.frame.area.stack.borrow_mut();\n        let v = stack.pop_float();\n        $interp.local.set_float($pos, v);\n    };\n    (double, $interp:ident, $pos:expr) => {\n        let mut stack = $interp.frame.area.stack.borrow_mut();\n        let v = stack.pop_double();\n        $interp.local.set_double($pos, v);\n    };\n    (a, $interp:ident, $pos:expr) => {\n        let mut stack = $interp.frame.area.stack.borrow_mut();\n        let v = stack.pop_ref();\n        $interp.local.set_ref($pos, v);\n    };\n}\n\nmacro_rules! opcode_math_op {\n    (int, $interp:ident, $op:ident) => {\n        let mut stack = $interp.frame.area.stack.borrow_mut();\n        let v2 = stack.pop_int();\n        let v1 = stack.pop_int();\n        let v = v1.$op(v2);\n        stack.push_int(v);\n    };\n    (long, $interp:ident, $op:ident) => {\n        let mut stack = $interp.frame.area.stack.borrow_mut();\n        let v2 = stack.pop_long();\n        let v1 = stack.pop_long();\n        let v = v1.$op(v2);\n        stack.push_long(v);\n    };\n    (float, $interp:ident, $op:ident) => {\n        let mut stack = $interp.frame.area.stack.borrow_mut();\n        let v2 = stack.pop_float();\n        let v1 = stack.pop_float();\n        let v = v1.$op(v2);\n        stack.push_float(v);\n    };\n    (double, $interp:ident, $op:ident) => {\n        let mut stack = $interp.frame.area.stack.borrow_mut();\n        let v2 = stack.pop_double();\n        let v1 = stack.pop_double();\n        let v = v1.$op(v2);\n        stack.push_double(v);\n    };\n}\n\nmacro_rules! opcode_if {\n    ($interp:ident, $op:tt) => {\n        let mut stack = $interp.frame.area.stack.borrow_mut();\n        let v2 = stack.pop_int();\n        let v1 = stack.pop_int();\n        if v1 $op v2 {\n            drop(stack);\n            $interp.goto_by_offset_hardcoded(2);\n        } else {\n            let _ = $interp.frame.pc.fetch_add(2, Ordering::Relaxed);\n        }\n    };\n    ($interp:ident, $op:tt, 0) => {\n        let mut stack = $interp.frame.area.stack.borrow_mut();\n        let v = stack.pop_int();\n        if v $op 0 {\n            drop(stack);\n            $interp.goto_by_offset_hardcoded(2);\n        } else {\n            let _ = $interp.frame.pc.fetch_add(2, Ordering::Relaxed);\n        }\n    };\n}\n\npub struct Interp<'a> {\n    frame: RwLockReadGuard<'a, Box<Frame>>,\n    local: Local,\n    cp: ConstantPool,\n    code: Arc<Vec<U1>>,\n    op_widen: bool,\n}\n\nimpl<'a> Interp<'a> {\n    pub fn new(frame: RwLockReadGuard<'a, Box<Frame>>, local: Local) -> Self {\n        let cp = frame.cp.clone();\n        let code = frame.code.clone();\n        let op_widen = false;\n        Self {\n            frame,\n            local,\n            cp,\n            code,\n            op_widen,\n        }\n    }\n}\n\nimpl<'a> Interp<'a> {\n    fn debug_op(&self, code: u8, op: OpCode) {\n        let frame_id = self.frame.frame_id;\n\n        trace!(\n            \"interp: {:?} ({}/{}) {:?}\",\n            op,\n            code,\n            frame_id,\n            self.frame.mir.method\n        );\n    }\n}\n\nimpl<'a> Interp<'a> {\n    pub fn run(&mut self) {\n        let jt = runtime::thread::current_java_thread();\n        let codes = self.code.clone();\n\n        loop {\n            let code = read_byte!(self.frame.pc, codes);\n            let code = OpCode::from(code);\n            match code {\n                OpCode::athrow => {\n                    self.athrow(jt);\n                    break;\n                }\n                OpCode::ireturn => {\n                    self.ireturn();\n                    break;\n                }\n                OpCode::lreturn => {\n                    self.lreturn();\n                    break;\n                }\n                OpCode::freturn => {\n                    self.freturn();\n                    break;\n                }\n                OpCode::dreturn => {\n                    self.dreturn();\n                    break;\n                }\n                OpCode::areturn => {\n                    self.areturn();\n                    break;\n                }\n                OpCode::return_void => {\n                    self.return_void();\n                    break;\n                }\n                OpCode::nop => (),\n                OpCode::aconst_null => {\n                    opcode_const!(null, self);\n                }\n                OpCode::iconst_m1 => {\n                    opcode_const!(m1, self);\n                }\n                OpCode::iconst_0 => {\n                    opcode_const!(0, self, false);\n                }\n                OpCode::iconst_1 => {\n                    opcode_const!(1, self, false);\n                }\n                OpCode::iconst_2 => {\n                    opcode_const!(2, self);\n                }\n                OpCode::iconst_3 => {\n                    opcode_const!(3, self);\n                }\n                OpCode::iconst_4 => {\n                    opcode_const!(4, self);\n                }\n                OpCode::iconst_5 => {\n                    opcode_const!(5, self);\n                }\n                OpCode::lconst_0 => {\n                    opcode_const!(0, self, true);\n                }\n                OpCode::lconst_1 => {\n                    opcode_const!(1, self, true);\n                }\n                OpCode::fconst_0 => {\n                    opcode_const!(0, self, false);\n                }\n                OpCode::fconst_1 => {\n                    opcode_const!(1, self, false);\n                }\n                OpCode::fconst_2 => {\n                    opcode_const!(2, self);\n                }\n                OpCode::dconst_0 => {\n                    opcode_const!(0, self, true);\n                }\n                OpCode::dconst_1 => {\n                    opcode_const!(1, self, true);\n                }\n                OpCode::bipush => self.bipush(),\n                OpCode::sipush => self.sipush(),\n                OpCode::ldc => self.ldc(),\n                OpCode::ldc_w => self.ldc_w(),\n                OpCode::ldc2_w => self.ldc2_w(),\n                OpCode::iload => {\n                    let pos = self.opcode_pos();\n                    opcode_load!(int, self, pos);\n                }\n                OpCode::lload => {\n                    let pos = self.opcode_pos();\n                    opcode_load!(long, self, pos);\n                }\n                OpCode::fload => {\n                    let pos = self.opcode_pos();\n                    opcode_load!(float, self, pos);\n                }\n                OpCode::dload => {\n                    let pos = self.opcode_pos();\n                    opcode_load!(double, self, pos);\n                }\n                OpCode::aload => {\n                    let pos = self.opcode_pos();\n                    opcode_load!(a, self, pos);\n                }\n                OpCode::iload_0 => {\n                    opcode_load!(int, self, 0);\n                }\n                OpCode::iload_1 => {\n                    opcode_load!(int, self, 1);\n                }\n                OpCode::iload_2 => {\n                    opcode_load!(int, self, 2);\n                }\n                OpCode::iload_3 => {\n                    opcode_load!(int, self, 3);\n                }\n                OpCode::lload_0 => {\n                    opcode_load!(long, self, 0);\n                }\n                OpCode::lload_1 => {\n                    opcode_load!(long, self, 1);\n                }\n                OpCode::lload_2 => {\n                    opcode_load!(long, self, 2);\n                }\n                OpCode::lload_3 => {\n                    opcode_load!(long, self, 3);\n                }\n                OpCode::fload_0 => {\n                    opcode_load!(float, self, 0);\n                }\n                OpCode::fload_1 => {\n                    opcode_load!(float, self, 1);\n                }\n                OpCode::fload_2 => {\n                    opcode_load!(float, self, 2);\n                }\n                OpCode::fload_3 => {\n                    opcode_load!(float, self, 3);\n                }\n                OpCode::dload_0 => {\n                    opcode_load!(double, self, 0);\n                }\n                OpCode::dload_1 => {\n                    opcode_load!(double, self, 1);\n                }\n                OpCode::dload_2 => {\n                    opcode_load!(double, self, 2);\n                }\n                OpCode::dload_3 => {\n                    opcode_load!(double, self, 3);\n                }\n                OpCode::aload_0 => {\n                    opcode_load!(a, self, 0);\n                }\n                OpCode::aload_1 => {\n                    opcode_load!(a, self, 1);\n                }\n                OpCode::aload_2 => {\n                    opcode_load!(a, self, 2);\n                }\n                OpCode::aload_3 => {\n                    opcode_load!(a, self, 3);\n                }\n                OpCode::iaload => self.iaload(),\n                OpCode::laload => self.laload(),\n                OpCode::faload => self.faload(),\n                OpCode::daload => self.daload(),\n                OpCode::aaload => self.aaload(),\n                OpCode::baload => self.baload(),\n                OpCode::caload => self.caload(),\n                OpCode::saload => self.saload(),\n                OpCode::istore => {\n                    let pos = self.opcode_pos();\n                    opcode_store!(int, self, pos);\n                }\n                OpCode::lstore => {\n                    let pos = self.opcode_pos();\n                    opcode_store!(long, self, pos);\n                }\n                OpCode::fstore => {\n                    let pos = self.opcode_pos();\n                    opcode_store!(float, self, pos);\n                }\n                OpCode::dstore => {\n                    let pos = self.opcode_pos();\n                    opcode_store!(double, self, pos);\n                }\n                OpCode::astore => {\n                    let pos = self.opcode_pos();\n                    opcode_store!(a, self, pos);\n                }\n                OpCode::istore_0 => {\n                    opcode_store!(int, self, 0);\n                }\n                OpCode::istore_1 => {\n                    opcode_store!(int, self, 1);\n                }\n                OpCode::istore_2 => {\n                    opcode_store!(int, self, 2);\n                }\n                OpCode::istore_3 => {\n                    opcode_store!(int, self, 3);\n                }\n                OpCode::lstore_0 => {\n                    opcode_store!(long, self, 0);\n                }\n                OpCode::lstore_1 => {\n                    opcode_store!(long, self, 1);\n                }\n                OpCode::lstore_2 => {\n                    opcode_store!(long, self, 2);\n                }\n                OpCode::lstore_3 => {\n                    opcode_store!(long, self, 3);\n                }\n                OpCode::fstore_0 => {\n                    opcode_store!(float, self, 0);\n                }\n                OpCode::fstore_1 => {\n                    opcode_store!(float, self, 1);\n                }\n                OpCode::fstore_2 => {\n                    opcode_store!(float, self, 2);\n                }\n                OpCode::fstore_3 => {\n                    opcode_store!(float, self, 3);\n                }\n                OpCode::dstore_0 => {\n                    opcode_store!(double, self, 0);\n                }\n                OpCode::dstore_1 => {\n                    opcode_store!(double, self, 1);\n                }\n                OpCode::dstore_2 => {\n                    opcode_store!(double, self, 2);\n                }\n                OpCode::dstore_3 => {\n                    opcode_store!(double, self, 3);\n                }\n                OpCode::astore_0 => {\n                    opcode_store!(a, self, 0);\n                }\n                OpCode::astore_1 => {\n                    opcode_store!(a, self, 1);\n                }\n                OpCode::astore_2 => {\n                    opcode_store!(a, self, 2);\n                }\n                OpCode::astore_3 => {\n                    opcode_store!(a, self, 3);\n                }\n                OpCode::iastore => self.iastore(),\n                OpCode::lastore => self.lastore(),\n                OpCode::fastore => self.fastore(),\n                OpCode::dastore => self.dastore(),\n                OpCode::aastore => self.aastore(),\n                OpCode::bastore => self.bastore(),\n                OpCode::castore => self.castore(),\n                OpCode::sastore => self.sastore(),\n                OpCode::pop => self.pop(),\n                OpCode::pop2 => self.pop2(),\n                OpCode::dup => self.dup(),\n                OpCode::dup_x1 => self.dup_x1(),\n                OpCode::dup_x2 => self.dup_x2(),\n                OpCode::dup2 => self.dup2(),\n                OpCode::dup2_x1 => self.dup2_x1(),\n                OpCode::dup2_x2 => self.dup2_x2(),\n                OpCode::swap => self.swap(),\n                OpCode::iadd => {\n                    opcode_math_op!(int, self, wrapping_add);\n                }\n                OpCode::ladd => {\n                    opcode_math_op!(long, self, wrapping_add);\n                }\n                OpCode::fadd => {\n                    use std::ops::Add;\n                    opcode_math_op!(float, self, add);\n                }\n                OpCode::dadd => {\n                    use std::ops::Add;\n                    opcode_math_op!(double, self, add);\n                }\n                OpCode::isub => {\n                    opcode_math_op!(int, self, wrapping_sub);\n                }\n                OpCode::lsub => {\n                    opcode_math_op!(long, self, wrapping_sub);\n                }\n                OpCode::fsub => {\n                    use std::ops::Sub;\n                    opcode_math_op!(float, self, sub);\n                }\n                OpCode::dsub => {\n                    use std::ops::Sub;\n                    opcode_math_op!(double, self, sub);\n                }\n                OpCode::imul => {\n                    opcode_math_op!(int, self, wrapping_mul);\n                }\n                OpCode::lmul => {\n                    opcode_math_op!(long, self, wrapping_mul);\n                }\n                OpCode::fmul => {\n                    use std::ops::Mul;\n                    opcode_math_op!(float, self, mul);\n                }\n                OpCode::dmul => {\n                    use std::ops::Mul;\n                    opcode_math_op!(double, self, mul);\n                }\n                OpCode::idiv => self.idiv(),\n                OpCode::ldiv => self.ldiv(),\n                OpCode::fdiv => self.fdiv(),\n                OpCode::ddiv => self.ddiv(),\n                OpCode::irem => self.irem(),\n                OpCode::lrem => self.lrem(),\n                OpCode::frem => self.frem(),\n                OpCode::drem => self.drem(),\n                OpCode::ineg => self.ineg(),\n                OpCode::lneg => self.lneg(),\n                OpCode::fneg => self.fneg(),\n                OpCode::dneg => self.dneg(),\n                OpCode::ishl => self.ishl(),\n                OpCode::lshl => self.lshl(),\n                OpCode::ishr => self.ishr(),\n                OpCode::lshr => self.lshr(),\n                OpCode::iushr => self.iushr(),\n                OpCode::lushr => self.lushr(),\n                OpCode::iand => {\n                    use std::ops::BitAnd;\n                    opcode_math_op!(int, self, bitand);\n                }\n                OpCode::land => {\n                    use std::ops::BitAnd;\n                    opcode_math_op!(long, self, bitand);\n                }\n                OpCode::ior => {\n                    use std::ops::BitOr;\n                    opcode_math_op!(int, self, bitor);\n                }\n                OpCode::lor => {\n                    use std::ops::BitOr;\n                    opcode_math_op!(long, self, bitor);\n                }\n                OpCode::ixor => {\n                    use std::ops::BitXor;\n                    opcode_math_op!(int, self, bitxor);\n                }\n                OpCode::lxor => {\n                    use std::ops::BitXor;\n                    opcode_math_op!(long, self, bitxor);\n                }\n                OpCode::iinc => self.iinc(),\n                OpCode::i2l => self.i2l(),\n                OpCode::i2f => self.i2f(),\n                OpCode::i2d => self.i2d(),\n                OpCode::l2i => self.l2i(),\n                OpCode::l2f => self.l2f(),\n                OpCode::l2d => self.l2d(),\n                OpCode::f2i => self.f2i(),\n                OpCode::f2l => self.f2l(),\n                OpCode::f2d => self.f2d(),\n                OpCode::d2i => self.d2i(),\n                OpCode::d2l => self.d2l(),\n                OpCode::d2f => self.d2f(),\n                OpCode::i2b => self.i2b(),\n                OpCode::i2c => self.i2c(),\n                OpCode::i2s => self.i2s(),\n                OpCode::lcmp => self.lcmp(),\n                OpCode::fcmpl => self.fcmpl(),\n                OpCode::fcmpg => self.fcmpg(),\n                OpCode::dcmpl => self.dcmpl(),\n                OpCode::dcmpg => self.dcmpg(),\n                OpCode::ifeq => {\n                    opcode_if!(self, ==, 0);\n                }\n                OpCode::ifne => {\n                    opcode_if!(self, !=, 0);\n                }\n                OpCode::iflt => {\n                    opcode_if!(self, <, 0);\n                }\n                OpCode::ifge => {\n                    opcode_if!(self, >=, 0);\n                }\n                OpCode::ifgt => {\n                    opcode_if!(self, >, 0);\n                }\n                OpCode::ifle => {\n                    opcode_if!(self, <=, 0);\n                }\n                OpCode::if_icmpeq => {\n                    opcode_if!(self, ==);\n                }\n                OpCode::if_icmpne => {\n                    opcode_if!(self, !=);\n                }\n                OpCode::if_icmplt => {\n                    opcode_if!(self, <);\n                }\n                OpCode::if_icmpge => {\n                    opcode_if!(self, >=);\n                }\n                OpCode::if_icmpgt => {\n                    opcode_if!(self, >);\n                }\n                OpCode::if_icmple => {\n                    opcode_if!(self, <=);\n                }\n                OpCode::if_acmpeq => self.if_acmpeq(),\n                OpCode::if_acmpne => self.if_acmpne(),\n                OpCode::goto => self.goto(),\n                OpCode::jsr => self.jsr(),\n                OpCode::ret => self.ret(),\n                OpCode::tableswitch => self.table_switch(),\n                OpCode::lookupswitch => self.lookup_switch(),\n                OpCode::getstatic => self.get_static(),\n                OpCode::putstatic => self.put_static(),\n                OpCode::getfield => self.get_field(),\n                OpCode::putfield => self.put_field(),\n                OpCode::invokevirtual => self.invoke_virtual(),\n                OpCode::invokespecial => self.invoke_special(),\n                OpCode::invokestatic => self.invoke_static(),\n                OpCode::invokeinterface => self.invoke_interface(),\n                OpCode::invokedynamic => self.invoke_dynamic(),\n                OpCode::new => self.new_(),\n                OpCode::newarray => self.new_array(),\n                OpCode::anewarray => self.anew_array(),\n                OpCode::arraylength => self.array_length(),\n                OpCode::checkcast => self.check_cast(),\n                OpCode::instanceof => self.instance_of(),\n                OpCode::monitorenter => self.monitor_enter(),\n                OpCode::monitorexit => self.monitor_exit(),\n                OpCode::wide => self.wide(),\n                OpCode::multianewarray => self.multi_anew_array(),\n                OpCode::ifnull => self.if_null(),\n                OpCode::ifnonnull => self.if_non_null(),\n                OpCode::goto_w => self.goto_w(),\n                OpCode::jsr_w => self.jsr_w(),\n                _ => unreachable!(),\n            }\n\n            let is_meet_ex = thread::is_meet_ex();\n            if is_meet_ex {\n                let mut th = jt.write().unwrap();\n                let ex = th.take_ex().unwrap();\n                drop(th);\n                match self.try_handle_exception(ex) {\n                    Ok(_) => (),\n                    Err(ex) => {\n                        let mut th = jt.write().unwrap();\n                        th.set_ex(ex);\n                        break;\n                    }\n                }\n            }\n        }\n    }\n}\n\n//helper methods\nimpl<'a> Interp<'a> {\n    fn load_constant(&self, pos: usize) {\n        match &self.cp[pos] {\n            ConstantPoolType::Integer { v } => {\n                let mut stack = self.frame.area.stack.borrow_mut();\n                stack.push_int2(v)\n            }\n            ConstantPoolType::Float { v } => {\n                let mut stack = self.frame.area.stack.borrow_mut();\n                stack.push_float2(v)\n            }\n            ConstantPoolType::Long { v } => {\n                let mut stack = self.frame.area.stack.borrow_mut();\n                stack.push_long2(v)\n            }\n            ConstantPoolType::Double { v } => {\n                let mut stack = self.frame.area.stack.borrow_mut();\n                stack.push_double2(v)\n            }\n            ConstantPoolType::String { string_index } => {\n                let s = get_cp_utf8(&self.cp, *string_index as usize);\n                let s = util::oop::new_java_lang_string3(s.as_slice());\n\n                let mut stack = self.frame.area.stack.borrow_mut();\n                stack.push_ref(s, false);\n            }\n            ConstantPoolType::Class { name_index } => {\n                let name = get_cp_utf8(&self.cp, *name_index as usize);\n                let name = unsafe { std::str::from_utf8_unchecked(name.as_slice()) };\n                let cl = { self.frame.class.get_class().class_loader };\n                trace!(\"load_constant name={}, cl={:?}\", name, cl);\n                let class = runtime::require_class3(cl, name.as_bytes()).unwrap();\n                oop::class::init_class(&class);\n                oop::class::init_class_fully(&class);\n\n                let mirror = { class.get_class().get_mirror() };\n                let mut stack = self.frame.area.stack.borrow_mut();\n                stack.push_ref(mirror, false);\n            }\n            _ => unreachable!(),\n        }\n    }\n\n    #[inline]\n    fn goto_abs(&self, pc: i32) {\n        self.frame.pc.store(pc, Ordering::Relaxed);\n    }\n\n    #[inline]\n    fn goto_by_offset(&self, branch: i32) {\n        let _ = self.frame.pc.fetch_add(branch, Ordering::Relaxed);\n    }\n\n    #[inline]\n    fn goto_by_offset_with_occupied(&self, branch: i32, occupied: i32) {\n        self.goto_by_offset(branch);\n        self.goto_by_offset(-(occupied - 1));\n    }\n\n    #[inline]\n    fn goto_by_offset_hardcoded(&self, occupied: i32) {\n        let codes = &self.code;\n        let pc = self.frame.pc.load(Ordering::Relaxed);\n        let high = codes[pc as usize] as i16;\n        let low = codes[(pc + 1) as usize] as i16;\n        let branch = (high << 8) | low;\n\n        self.goto_by_offset_with_occupied(branch as i32, occupied);\n    }\n\n    #[inline]\n    fn goto_abs_with_occupied(&self, pc: i32, occupied: i32) {\n        self.goto_abs(pc);\n        self.goto_by_offset(-(occupied - 1));\n    }\n\n    fn set_return(&self, v: Option<Oop>) {\n        let mut return_v = self.frame.area.return_v.borrow_mut();\n        *return_v = v;\n    }\n\n    fn get_field_helper(&self, receiver: Oop, idx: usize, is_static: bool) {\n        let class = self.frame.class.extract_inst();\n        let fir = class.cp_cache.get_field(idx, is_static);\n        debug_assert_eq!(fir.field.is_static(), is_static);\n        trace!(\"get_field_helper={:?}, is_static={}\", fir.field, is_static);\n        let value_type = fir.field.value_type;\n        let v = if is_static {\n            let class = fir.field.class.get_class();\n            class.get_static_field_value(fir.clone())\n        } else {\n            let rf = receiver.extract_ref();\n            Class::get_field_value2(rf, fir.offset)\n        };\n        let with_nop = match value_type {\n            ValueType::DOUBLE | ValueType::LONG => true,\n            _ => false,\n        };\n        let mut stack = self.frame.area.stack.borrow_mut();\n        stack.push_ref(v, with_nop);\n    }\n\n    fn pop_value(&self, vt: ValueType) -> Oop {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        match vt {\n            ValueType::INT\n            | ValueType::SHORT\n            | ValueType::CHAR\n            | ValueType::BOOLEAN\n            | ValueType::BYTE => {\n                let v = stack.pop_int();\n                Oop::new_int(v)\n            }\n            ValueType::FLOAT => {\n                let v = stack.pop_float();\n                Oop::new_float(v)\n            }\n            ValueType::DOUBLE => {\n                let v = stack.pop_double();\n                Oop::new_double(v)\n            }\n            ValueType::LONG => {\n                let v = stack.pop_long();\n                Oop::new_long(v)\n            }\n            ValueType::ARRAY | ValueType::OBJECT => stack.pop_ref(),\n            _ => unreachable!(),\n        }\n    }\n\n    fn put_field_helper(&self, idx: usize, is_static: bool) {\n        let class = self.frame.class.extract_inst();\n        let fir = class.cp_cache.get_field(idx, is_static);\n        debug_assert_eq!(fir.field.is_static(), is_static);\n        trace!(\"put_field_helper={:?}, is_static={}\", fir.field, is_static);\n        let value_type = fir.field.value_type;\n        //        info!(\"value_type = {:?}\", value_type);\n        let v = self.pop_value(value_type);\n        if is_static {\n            let mut class = fir.field.class.get_mut_class();\n            class.put_static_field_value(fir.clone(), v);\n        } else {\n            let receiver = {\n                let mut stack = self.frame.area.stack.borrow_mut();\n                stack.pop_ref()\n            };\n            match receiver {\n                Oop::Null => exception::meet_ex(cls_const::J_NPE, None),\n                _ => Class::put_field_value2(receiver.extract_ref(), fir.offset, v),\n            }\n        }\n    }\n\n    fn invoke_helper(&self, is_static: bool, idx: usize, force_no_resolve: bool) {\n        let class = self.frame.class.extract_inst();\n        let mir = class.cp_cache.get_method(idx);\n        let caller = match &mir.method.signature.retype {\n            classfile::SignatureType::Void => None,\n            _ => Some(&self.frame.area),\n        };\n        debug_assert_eq!(mir.method.is_static(), is_static);\n        if let Ok(mut jc) = runtime::invoke::JavaCall::new(&self.frame.area, mir) {\n            jc.invoke(caller, force_no_resolve);\n        }\n    }\n\n    pub fn check_cast_helper(&self, is_cast: bool) {\n        let pc = &self.frame.pc;\n        let codes = &self.code;\n        let cp_idx = read_i2!(pc, codes);\n        let target_cls = require_class2(cp_idx as U2, &self.cp).unwrap();\n        let obj_rf = self.pop_value(ValueType::OBJECT);\n        let obj_rf_clone = obj_rf.clone();\n        let op_check_cast = |r: bool, obj_cls: ClassRef, target_cls: ClassRef| {\n            if r {\n                let mut stack = self.frame.area.stack.borrow_mut();\n                stack.push_ref(obj_rf_clone, false);\n            } else {\n                let obj_name = { obj_cls.get_class().name.clone() };\n                let target_name = { target_cls.get_class().name.clone() };\n\n                let obj_name = String::from_utf8_lossy(obj_name.as_slice()).replace(\"/\", \".\");\n                let target_name = String::from_utf8_lossy(target_name.as_slice()).replace(\"/\", \".\");\n\n                let msg = format!(\"{} cannot be cast to {}\", obj_name, target_name);\n                exception::meet_ex(cls_const::J_CCE, Some(msg));\n            }\n        };\n        let op_instance_of = |r: bool| {\n            let mut stack = self.frame.area.stack.borrow_mut();\n            if r {\n                stack.push_const1(false);\n            } else {\n                stack.push_const0(false);\n            }\n        };\n\n        match obj_rf {\n            Oop::Null => {\n                let mut stack = self.frame.area.stack.borrow_mut();\n                if is_cast {\n                    stack.push_ref(obj_rf, false);\n                } else {\n                    stack.push_const0(false);\n                }\n            }\n            Oop::Ref(rf) => {\n                let rf = rf.get_raw_ptr();\n                unsafe {\n                    match &(*rf).v {\n                        oop::RefKind::Inst(inst) => {\n                            let obj_cls = inst.class.clone();\n                            let r = cmp::instance_of(obj_cls.clone(), target_cls.clone());\n\n                            if is_cast {\n                                op_check_cast(r, obj_cls, target_cls);\n                            } else {\n                                op_instance_of(r);\n                            }\n                        }\n\n                        oop::RefKind::Array(ary) => {\n                            let obj_cls = ary.class.clone();\n                            let r = cmp::instance_of(obj_cls.clone(), target_cls.clone());\n                            if is_cast {\n                                op_check_cast(r, obj_cls, target_cls);\n                            } else {\n                                op_instance_of(r);\n                            }\n                        }\n                        oop::RefKind::Mirror(mirror) => {\n                            //run here codes:\n                            //$JDK_TEST/Appendable/Basic.java\n                            //Will eventually call java.security.Security.getSpiClass (\"MessageDigest\"):\n                            //Exception in thread \"main\" java.lang.ClassCastException: java.security.MessageDigestSpi cannot be cast to java.lang.Class\n\n                            let obj_cls = mirror.target.clone().unwrap();\n                            let target_name = target_cls.get_class().name.as_slice();\n                            let r = target_name == b\"java/lang/Class\"\n                                || cmp::instance_of(obj_cls.clone(), target_cls.clone());\n\n                            if is_cast {\n                                op_check_cast(r, obj_cls, target_cls);\n                            } else {\n                                op_instance_of(r);\n                            }\n                        }\n                        _ => unreachable!(),\n                    }\n                }\n            }\n            _ => unreachable!(),\n        }\n    }\n\n    #[inline]\n    fn opcode_pos(&mut self) -> usize {\n        let pc = &self.frame.pc;\n        let codes = &self.code;\n        let op_widen = self.op_widen;\n        if op_widen {\n            self.op_widen = false;\n            read_u2!(pc, codes)\n        } else {\n            read_u1!(pc, codes)\n        }\n    }\n}\n\n//handle exception\nimpl<'a> Interp<'a> {\n    fn try_handle_exception(&self, ex: Oop) -> Result<(), Oop> {\n        let ex_cls = {\n            let rf = ex.extract_ref();\n            let inst = rf.extract_inst();\n            inst.class.clone()\n        };\n\n        let handler = {\n            let pc = self.frame.pc.load(Ordering::Relaxed);\n            self.frame\n                .mir\n                .method\n                .find_exception_handler(&self.cp, pc as u16, ex_cls)\n        };\n\n        match handler {\n            Some(pc) => {\n                let mut stack = self.frame.area.stack.borrow_mut();\n                stack.clear();\n                stack.push_ref(ex, false);\n                drop(stack);\n\n                let line_num = self.frame.mir.method.get_line_num(pc);\n\n                info!(\n                    \"Found Exception Handler: line={}, frame_id={}, {:?}\",\n                    line_num, self.frame.frame_id, self.frame.mir.method\n                );\n\n                self.goto_abs(pc as i32);\n                Ok(())\n            }\n\n            None => {\n                let pc = self.frame.pc.load(Ordering::Relaxed);\n                let line_num = self.frame.mir.method.get_line_num(pc as u16);\n\n                info!(\n                    \"NotFound Exception Handler: line={}, frame_id={}, {:?}\",\n                    line_num, self.frame.frame_id, self.frame.mir.method,\n                );\n\n                Err(ex)\n            }\n        }\n    }\n}\n\n//byte code impl\nimpl<'a> Interp<'a> {\n    #[inline]\n    fn sipush(&self) {\n        let pc = &self.frame.pc;\n        let codes = &self.code;\n        let v = read_i2!(pc, codes);\n        let mut stack = self.frame.area.stack.borrow_mut();\n        stack.push_int(v);\n    }\n\n    #[inline]\n    fn bipush(&self) {\n        let pc = &self.frame.pc;\n        let codes = &self.code;\n        let v = (read_byte!(pc, codes) as i8) as i32;\n        let mut stack = self.frame.area.stack.borrow_mut();\n        stack.push_int(v);\n    }\n\n    #[inline]\n    fn ldc(&self) {\n        let pc = &self.frame.pc;\n        let codes = &self.code;\n        let pos = read_u1!(pc, codes);\n        self.load_constant(pos);\n    }\n\n    #[inline]\n    fn ldc_w(&self) {\n        let pc = &self.frame.pc;\n        let codes = &self.code;\n        let pos = read_u2!(pc, codes);\n        self.load_constant(pos);\n    }\n\n    #[inline]\n    fn ldc2_w(&self) {\n        self.ldc_w();\n    }\n\n    #[inline]\n    fn iaload(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let pos = stack.pop_int();\n        let rf = stack.pop_ref();\n        match rf {\n            Oop::Null => exception::meet_ex(cls_const::J_NPE, None),\n            Oop::Ref(rf) => {\n                let ary = rf.extract_type_array();\n                let ary = ary.extract_ints();\n                iarray_load!(stack, ary, pos);\n            }\n            _ => unreachable!(),\n        }\n    }\n\n    #[inline]\n    fn saload(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let pos = stack.pop_int();\n        let rf = stack.pop_ref();\n        match rf {\n            Oop::Null => exception::meet_ex(cls_const::J_NPE, None),\n            Oop::Ref(rf) => {\n                let ary = rf.extract_type_array();\n                let ary = ary.extract_shorts();\n                iarray_load!(stack, ary, pos);\n            }\n            _ => unreachable!(),\n        }\n    }\n\n    #[inline]\n    fn caload(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let pos = stack.pop_int();\n        let rf = stack.pop_ref();\n        match rf {\n            Oop::Null => exception::meet_ex(cls_const::J_NPE, None),\n            Oop::Ref(rf) => {\n                let ary = rf.extract_type_array();\n                let ary = ary.extract_chars();\n                iarray_load!(stack, ary, pos);\n            }\n            _ => unreachable!(),\n        }\n    }\n\n    #[inline]\n    fn baload(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let pos = stack.pop_int();\n        let rf = stack.pop_ref();\n        match rf {\n            Oop::Null => exception::meet_ex(cls_const::J_NPE, None),\n            Oop::Ref(rf) => {\n                let mut rf = (*rf).get_raw_ptr();\n                unsafe {\n                    let ary = (*rf).v.extract_type_array();\n                    let len = ary.len();\n\n                    if (pos < 0) || (pos as usize >= len) {\n                        let msg = format!(\"length is {}, but index is {}\", len, pos);\n                        exception::meet_ex(cls_const::J_ARRAY_INDEX_OUT_OF_BOUNDS, Some(msg));\n                    } else {\n                        match ary {\n                            TypeArrayDesc::Byte(ary) => {\n                                let v = ary[pos as usize];\n                                stack.push_int(v as i32);\n                            }\n                            TypeArrayDesc::Bool(ary) => {\n                                let v = ary[pos as usize];\n                                stack.push_int(v as i32);\n                            }\n                            t => unreachable!(\"t = {:?}\", t),\n                        }\n                    }\n                }\n            }\n            _ => unreachable!(),\n        }\n    }\n\n    #[inline]\n    fn laload(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let pos = stack.pop_int();\n        let rf = stack.pop_ref();\n        match rf {\n            Oop::Null => exception::meet_ex(cls_const::J_NPE, None),\n            Oop::Ref(rf) => {\n                let ary = rf.extract_type_array();\n                let ary = ary.extract_longs();\n                let len = ary.len();\n                if (pos < 0) || (pos as usize >= len) {\n                    let msg = format!(\"length is {}, but index is {}\", len, pos);\n                    exception::meet_ex(cls_const::J_ARRAY_INDEX_OUT_OF_BOUNDS, Some(msg));\n                } else {\n                    let v = ary[pos as usize];\n                    stack.push_long(v);\n                }\n            }\n            _ => unreachable!(),\n        }\n    }\n\n    #[inline]\n    fn faload(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let pos = stack.pop_int();\n        let rf = stack.pop_ref();\n        match rf {\n            Oop::Null => exception::meet_ex(cls_const::J_NPE, None),\n            Oop::Ref(rf) => {\n                let ary = rf.extract_type_array();\n                let ary = ary.extract_floats();\n                let len = ary.len();\n                if (pos < 0) || (pos as usize >= len) {\n                    let msg = format!(\"length is {}, but index is {}\", len, pos);\n                    exception::meet_ex(cls_const::J_ARRAY_INDEX_OUT_OF_BOUNDS, Some(msg));\n                } else {\n                    let v = ary[pos as usize];\n                    stack.push_float(v);\n                }\n            }\n            _ => unreachable!(),\n        }\n    }\n\n    #[inline]\n    fn daload(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let pos = stack.pop_int();\n        let rf = stack.pop_ref();\n        match rf {\n            Oop::Null => exception::meet_ex(cls_const::J_NPE, None),\n            Oop::Ref(rf) => {\n                let ary = rf.extract_type_array();\n                let ary = ary.extract_doubles();\n                let len = ary.len();\n                if (pos < 0) || (pos as usize >= len) {\n                    let msg = format!(\"length is {}, but index is {}\", len, pos);\n                    exception::meet_ex(cls_const::J_ARRAY_INDEX_OUT_OF_BOUNDS, Some(msg));\n                } else {\n                    let v = ary[pos as usize];\n                    stack.push_double(v);\n                }\n            }\n            _ => unreachable!(),\n        }\n    }\n\n    #[inline]\n    fn aaload(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let pos = stack.pop_int();\n        let rf = stack.pop_ref();\n        match rf {\n            Oop::Null => exception::meet_ex(cls_const::J_NPE, None),\n            Oop::Ref(rf) => {\n                let ary = rf.extract_array();\n                let ary = &ary.elements;\n                let len = ary.len();\n\n                if (pos < 0) || (pos as usize >= len) {\n                    let msg = format!(\"length is {}, but index is {}\", len, pos);\n                    exception::meet_ex(cls_const::J_ARRAY_INDEX_OUT_OF_BOUNDS, Some(msg));\n                } else {\n                    let v = ary[pos as usize].clone();\n                    stack.push_ref(v, false);\n                }\n            }\n            _ => unreachable!(),\n        }\n    }\n\n    #[inline]\n    fn bastore(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v = stack.pop_int();\n        let pos = stack.pop_int();\n        let rf = stack.pop_ref();\n        drop(stack);\n\n        match rf {\n            Oop::Null => exception::meet_ex(cls_const::J_NPE, None),\n            Oop::Ref(rf) => {\n                let mut rf = (*rf).get_mut_raw_ptr();\n                unsafe {\n                    let ary = (*rf).v.extract_mut_type_array();\n                    match ary {\n                        oop::TypeArrayDesc::Byte(ary) => {\n                            let v = v as u8;\n                            array_store!(ary, pos, v);\n                        }\n                        oop::TypeArrayDesc::Bool(ary) => {\n                            let v = v as u8;\n                            array_store!(ary, pos, v);\n                        }\n                        _ => unreachable!(),\n                    }\n                }\n            }\n            _ => unreachable!(),\n        }\n    }\n\n    #[inline]\n    fn castore(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v = stack.pop_int();\n        let pos = stack.pop_int();\n        let rf = stack.pop_ref();\n        drop(stack);\n\n        match rf {\n            Oop::Null => exception::meet_ex(cls_const::J_NPE, None),\n            Oop::Ref(rf) => {\n                let ary = rf.extract_mut_type_array();\n                let ary = ary.extract_mut_chars();\n                let v = v as u16;\n                array_store!(ary, pos, v);\n            }\n            _ => unreachable!(),\n        }\n    }\n\n    #[inline]\n    fn sastore(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v = stack.pop_int();\n        let pos = stack.pop_int();\n        let rf = stack.pop_ref();\n        drop(stack);\n\n        match rf {\n            Oop::Null => exception::meet_ex(cls_const::J_NPE, None),\n            Oop::Ref(rf) => {\n                let ary = rf.extract_mut_type_array();\n                let ary = ary.extract_mut_shorts();\n                let v = v as i16;\n                array_store!(ary, pos, v);\n            }\n            _ => unreachable!(),\n        }\n    }\n\n    #[inline]\n    fn iastore(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v = stack.pop_int();\n        let pos = stack.pop_int();\n        let rf = stack.pop_ref();\n        drop(stack);\n\n        match rf {\n            Oop::Null => exception::meet_ex(cls_const::J_NPE, None),\n            Oop::Ref(rf) => {\n                let ary = rf.extract_mut_type_array();\n                let ary = ary.extract_mut_ints();\n                array_store!(ary, pos, v);\n            }\n            _ => unreachable!(),\n        }\n    }\n\n    #[inline]\n    fn lastore(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v = stack.pop_long();\n        let pos = stack.pop_int();\n        let rf = stack.pop_ref();\n        drop(stack);\n\n        match rf {\n            Oop::Null => exception::meet_ex(cls_const::J_NPE, None),\n            Oop::Ref(rf) => {\n                let ary = rf.extract_mut_type_array();\n                let ary = ary.extract_mut_longs();\n                array_store!(ary, pos, v);\n            }\n            _ => unreachable!(),\n        }\n    }\n\n    #[inline]\n    fn fastore(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v = stack.pop_float();\n        let pos = stack.pop_int();\n        let rf = stack.pop_ref();\n        drop(stack);\n\n        match rf {\n            Oop::Null => exception::meet_ex(cls_const::J_NPE, None),\n            Oop::Ref(rf) => {\n                let ary = rf.extract_mut_type_array();\n                let ary = ary.extract_mut_floats();\n                array_store!(ary, pos, v);\n            }\n            _ => unreachable!(),\n        }\n    }\n\n    #[inline]\n    fn dastore(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v = stack.pop_double();\n        let pos = stack.pop_int();\n        let rf = stack.pop_ref();\n        drop(stack);\n\n        match rf {\n            Oop::Null => exception::meet_ex(cls_const::J_NPE, None),\n            Oop::Ref(rf) => {\n                let ary = rf.extract_mut_type_array();\n                let ary = ary.extract_mut_doubles();\n                array_store!(ary, pos, v);\n            }\n            _ => unreachable!(),\n        }\n    }\n\n    #[inline]\n    fn aastore(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v = stack.pop_ref();\n        let pos = stack.pop_int();\n        let ary_rf = stack.pop_ref();\n        drop(stack);\n\n        match ary_rf {\n            Oop::Null => exception::meet_ex(cls_const::J_NPE, None),\n            Oop::Ref(rf) => {\n                let ary = rf.extract_mut_array();\n                let ary = &mut ary.elements;\n                array_store!(ary, pos, v);\n            }\n            _ => unreachable!(),\n        }\n    }\n\n    #[inline]\n    fn pop(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        stack.drop_top();\n    }\n\n    #[inline]\n    fn pop2(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        stack.drop_top();\n        stack.drop_top();\n    }\n\n    #[inline]\n    fn dup(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        stack.dup();\n    }\n\n    #[inline]\n    fn dup_x1(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        stack.dup_x1();\n    }\n\n    #[inline]\n    fn dup_x2(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        stack.dup_x2();\n    }\n\n    #[inline]\n    fn dup2(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        stack.dup2();\n    }\n\n    #[inline]\n    fn dup2_x1(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        stack.dup2_x1();\n    }\n\n    #[inline]\n    fn dup2_x2(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        stack.dup2_x2();\n    }\n\n    #[inline]\n    fn swap(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        stack.swap();\n    }\n\n    #[inline]\n    fn idiv(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v2 = stack.pop_int();\n        let v1 = stack.pop_int();\n        if v2 == 0 {\n            drop(stack);\n            exception::meet_ex(\n                cls_const::J_ARITHMETIC_EX,\n                Some(\"divide by zero\".to_string()),\n            );\n        } else {\n            stack.push_int(v1 / v2);\n        }\n    }\n\n    #[inline]\n    fn ldiv(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v2 = stack.pop_long();\n        let v1 = stack.pop_long();\n        if v2 == 0 {\n            drop(stack);\n            exception::meet_ex(\n                cls_const::J_ARITHMETIC_EX,\n                Some(\"divide by zero\".to_string()),\n            );\n        } else {\n            stack.push_long(v1 / v2);\n        }\n    }\n\n    #[inline]\n    fn fdiv(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v2 = stack.pop_float();\n        let v1 = stack.pop_float();\n        if v2 == 0.0 {\n            drop(stack);\n            exception::meet_ex(\n                cls_const::J_ARITHMETIC_EX,\n                Some(\"divide by zero\".to_string()),\n            );\n        } else {\n            stack.push_float(v1 / v2);\n        }\n    }\n\n    #[inline]\n    fn ddiv(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v2 = stack.pop_double();\n        let v1 = stack.pop_double();\n        if v2 == 0.0 {\n            drop(stack);\n            exception::meet_ex(\n                cls_const::J_ARITHMETIC_EX,\n                Some(\"divide by zero\".to_string()),\n            );\n        } else {\n            stack.push_double(v1 / v2);\n        }\n    }\n\n    #[inline]\n    fn irem(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v2 = stack.pop_int();\n        let v1 = stack.pop_int();\n        if v2 == 0 {\n            drop(stack);\n            exception::meet_ex(\n                cls_const::J_ARITHMETIC_EX,\n                Some(\"divide by zero\".to_string()),\n            );\n        } else {\n            stack.push_int(v1 - (v1 / v2) * v2);\n        }\n    }\n\n    #[inline]\n    fn lrem(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v2 = stack.pop_long();\n        let v1 = stack.pop_long();\n        if v2 == 0 {\n            drop(stack);\n            exception::meet_ex(\n                cls_const::J_ARITHMETIC_EX,\n                Some(\"divide by zero\".to_string()),\n            );\n        } else {\n            stack.push_long(v1 - (v1 / v2) * v2);\n        }\n    }\n\n    #[inline]\n    fn frem(&self) {\n        panic!(\"Use of deprecated instruction frem, please check your Java compiler\");\n    }\n\n    #[inline]\n    fn drem(&self) {\n        panic!(\"Use of deprecated instruction drem, please check your Java compiler\");\n    }\n\n    #[inline]\n    fn ineg(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v = stack.pop_int();\n        stack.push_int(-v);\n    }\n\n    #[inline]\n    fn lneg(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v = stack.pop_long();\n        stack.push_long(-v);\n    }\n\n    #[inline]\n    fn fneg(&self) {\n        panic!(\"Use of deprecated instruction fneg, please check your Java compiler\");\n    }\n\n    #[inline]\n    fn dneg(&self) {\n        panic!(\"Use of deprecated instruction dneg, please check your Java compiler\");\n    }\n\n    #[inline]\n    fn ishl(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v2 = stack.pop_int();\n        let v1 = stack.pop_int();\n        let s = v2 & 0x1F;\n        stack.push_int(v1 << s);\n    }\n\n    #[inline]\n    fn lshl(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v2 = stack.pop_int();\n        let v1 = stack.pop_long();\n        let s = (v2 & 0x3F) as i64;\n        stack.push_long(v1 << s);\n    }\n\n    #[inline]\n    fn ishr(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v2 = stack.pop_int();\n        let v1 = stack.pop_int();\n        let s = v2 & 0x1F;\n        stack.push_int(v1 >> s);\n    }\n\n    #[inline]\n    fn lshr(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v2 = stack.pop_int();\n        let v1 = stack.pop_long();\n        let s = (v2 & 0x3F) as i64;\n        stack.push_long(v1 >> s);\n    }\n\n    #[inline]\n    fn iushr(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v2 = stack.pop_int();\n        let v1 = stack.pop_int() as u32;\n        let s = (v2 & 0x1F) as u32;\n        stack.push_int((v1 >> s) as i32);\n    }\n\n    #[inline]\n    fn lushr(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v2 = stack.pop_int();\n        let v1 = stack.pop_long() as u64;\n        let s = (v2 & 0x3F) as u64;\n        stack.push_long((v1 >> s) as i64);\n    }\n\n    #[inline]\n    fn iinc(&mut self) {\n        let pc = &self.frame.pc;\n        let codes = &self.code;\n        let op_widen = self.op_widen;\n        let pos;\n        let factor;\n        if op_widen {\n            self.op_widen = false;\n            pos = read_u2!(pc, codes);\n            factor = (read_u2!(pc, codes) as i16) as i32\n        } else {\n            pos = read_u1!(pc, codes);\n            factor = (read_byte!(pc, codes) as i8) as i32\n        };\n\n        let v = self.local.get_int(pos);\n        let v = v.wrapping_add(factor);\n        self.local.set_int(pos, v);\n    }\n\n    #[inline]\n    fn i2l(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v = stack.pop_int();\n        stack.push_long(v as i64);\n    }\n\n    #[inline]\n    fn i2f(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v = stack.pop_int();\n        stack.push_float(v as f32);\n    }\n\n    #[inline]\n    fn i2d(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v = stack.pop_int();\n        stack.push_double(v as f64);\n    }\n\n    #[inline]\n    fn l2i(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v = stack.pop_long();\n        stack.push_int(v as i32);\n    }\n\n    #[inline]\n    fn l2f(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v = stack.pop_long();\n        stack.push_float(v as f32);\n    }\n\n    #[inline]\n    fn l2d(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v = stack.pop_long();\n        stack.push_double(v as f64);\n    }\n\n    #[inline]\n    fn f2i(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v = stack.pop_float();\n        if v.is_nan() {\n            stack.push_int(0);\n        } else if v.is_infinite() {\n            if v.is_sign_positive() {\n                stack.push_int(i32::MAX);\n            } else {\n                stack.push_int(i32::MIN);\n            }\n        } else {\n            stack.push_int(v as i32);\n        }\n    }\n\n    #[inline]\n    fn f2l(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v = stack.pop_float();\n        if v.is_nan() {\n            stack.push_long(0);\n        } else if v.is_infinite() {\n            if v.is_sign_positive() {\n                stack.push_long(i64::MAX);\n            } else {\n                stack.push_long(i64::MIN);\n            }\n        } else {\n            stack.push_long(v as i64);\n        }\n    }\n\n    #[inline]\n    fn f2d(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v = stack.pop_float();\n        stack.push_double(v as f64);\n    }\n\n    #[inline]\n    fn d2i(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v = stack.pop_double();\n        if v.is_nan() {\n            stack.push_int(0);\n        } else if v.is_infinite() {\n            if v.is_sign_positive() {\n                stack.push_int(i32::MAX);\n            } else {\n                stack.push_int(i32::MIN);\n            }\n        } else {\n            stack.push_int(v as i32);\n        }\n    }\n\n    #[inline]\n    fn d2l(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v = stack.pop_double();\n        if v.is_nan() {\n            stack.push_long(0);\n        } else if v.is_infinite() {\n            if v.is_sign_positive() {\n                stack.push_long(i64::MAX);\n            } else {\n                stack.push_long(i64::MIN);\n            }\n        } else {\n            stack.push_long(v as i64);\n        }\n    }\n\n    #[inline]\n    fn d2f(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v = stack.pop_double();\n        stack.push_float(v as f32);\n    }\n\n    #[inline]\n    fn i2b(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v = stack.pop_int();\n        let v = v as i8;\n        stack.push_int(v as i32);\n    }\n\n    #[inline]\n    fn i2c(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v = stack.pop_int();\n        let v = v as u16;\n        stack.push_int(v as i32);\n    }\n\n    #[inline]\n    fn i2s(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v = stack.pop_int();\n        let v = v as i16;\n        stack.push_int(v as i32);\n    }\n\n    #[inline]\n    fn lcmp(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v1 = stack.pop_long();\n        let v2 = stack.pop_long();\n        let v = match v1.cmp(&v2) {\n            std::cmp::Ordering::Greater => -1,\n            std::cmp::Ordering::Less => 1,\n            std::cmp::Ordering::Equal => 0,\n        };\n        stack.push_int(v);\n    }\n\n    #[inline]\n    fn fcmpl(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v1 = stack.pop_float();\n        let v2 = stack.pop_float();\n        let v = if v1.is_nan() || v2.is_nan() {\n            -1\n        } else if v1 > v2 {\n            -1\n        } else if v1 < v2 {\n            1\n        } else {\n            0\n        };\n        stack.push_int(v);\n    }\n\n    #[inline]\n    fn fcmpg(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v1 = stack.pop_float();\n        let v2 = stack.pop_float();\n        let v = if v1.is_nan() || v2.is_nan() {\n            1\n        } else if v1 > v2 {\n            -1\n        } else if v1 < v2 {\n            1\n        } else {\n            0\n        };\n        stack.push_int(v);\n    }\n\n    #[inline]\n    fn dcmpl(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v1 = stack.pop_double();\n        let v2 = stack.pop_double();\n        let v = if v1.is_nan() || v2.is_nan() {\n            -1\n        } else if v1 > v2 {\n            -1\n        } else if v1 < v2 {\n            1\n        } else {\n            0\n        };\n        stack.push_int(v);\n    }\n\n    #[inline]\n    fn dcmpg(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v1 = stack.pop_double();\n        let v2 = stack.pop_double();\n        if v1.is_nan() || v2.is_nan() {\n            stack.push_int(1);\n        } else if v1 > v2 {\n            stack.push_int(-1);\n        } else if v1 < v2 {\n            stack.push_int(1);\n        } else {\n            stack.push_int(0);\n        }\n    }\n\n    #[inline]\n    fn if_acmpeq(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v2 = stack.pop_ref();\n        let v1 = stack.pop_ref();\n        if OopPtr::is_eq(&v1, &v2) {\n            drop(stack);\n            self.goto_by_offset_hardcoded(2);\n        } else {\n            let _ = self.frame.pc.fetch_add(2, Ordering::Relaxed);\n        }\n    }\n\n    #[inline]\n    fn if_acmpne(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v2 = stack.pop_ref();\n        let v1 = stack.pop_ref();\n        if !OopPtr::is_eq(&v1, &v2) {\n            drop(stack);\n            self.goto_by_offset_hardcoded(2);\n        } else {\n            let _ = self.frame.pc.fetch_add(2, Ordering::Relaxed);\n        }\n    }\n\n    #[inline]\n    fn goto(&self) {\n        self.goto_by_offset_hardcoded(2);\n    }\n\n    #[inline]\n    fn jsr(&self) {\n        let _ = self.frame.pc.fetch_add(2, Ordering::Relaxed);\n        panic!(\"Use of deprecated instruction jsr, please check your Java compiler\");\n    }\n\n    #[inline]\n    fn ret(&mut self) {\n        let pc = &self.frame.pc;\n        let codes = &self.code;\n        let op_widen = self.op_widen;\n        let new_pc = if op_widen {\n            self.op_widen = false;\n            read_u2!(pc, codes)\n        } else {\n            read_u1!(pc, codes)\n        };\n        pc.store(new_pc as i32, Ordering::Relaxed);\n    }\n\n    #[inline]\n    fn table_switch(&self) {\n        let pc = &self.frame.pc;\n        let codes = &self.code;\n        let mut bc = pc.load(Ordering::Relaxed) - 1;\n\n        let origin_bc = bc;\n        if bc % 4 != 0 {\n            bc += (4 - bc % 4);\n        } else {\n            bc += 4;\n        }\n        let mut ptr = bc as usize;\n\n        let default_byte = [codes[ptr], codes[ptr + 1], codes[ptr + 2], codes[ptr + 3]];\n        let default_byte = i32::from_be_bytes(default_byte);\n        let low_byte = [\n            codes[ptr + 4],\n            codes[ptr + 5],\n            codes[ptr + 6],\n            codes[ptr + 7],\n        ];\n        let low_byte = i32::from_be_bytes(low_byte);\n        let high_byte = [\n            codes[ptr + 8],\n            codes[ptr + 9],\n            codes[ptr + 10],\n            codes[ptr + 11],\n        ];\n        let high_byte = i32::from_be_bytes(high_byte);\n        let num = high_byte - low_byte + 1;\n        ptr += 12;\n\n        // switch-case jump table\n        let mut jump_table = Vec::with_capacity(num as usize);\n        for pos in 0..num {\n            let pos = [codes[ptr], codes[ptr + 1], codes[ptr + 2], codes[ptr + 3]];\n            let pos = i32::from_be_bytes(pos);\n            let jump_pos = pos + origin_bc;\n            ptr += 4;\n            jump_table.push(jump_pos);\n        }\n        // default\n        jump_table.push(default_byte + origin_bc);\n\n        let top_value = {\n            let mut stack = self.frame.area.stack.borrow_mut();\n            stack.pop_int()\n        };\n        if (top_value > (jump_table.len() as i32 - 1 + low_byte)) || top_value < low_byte {\n            self.goto_abs_with_occupied(*jump_table.last().unwrap() as i32, 1);\n        } else {\n            self.goto_abs_with_occupied(\n                jump_table[(top_value - low_byte as i32) as usize] as i32,\n                1,\n            );\n        }\n    }\n\n    #[inline]\n    fn lookup_switch(&self) {\n        let pc = &self.frame.pc;\n        let codes = &self.code;\n        let mut bc = pc.load(Ordering::Relaxed) - 1;\n\n        let origin_bc = bc;\n        if bc % 4 != 0 {\n            bc += (4 - bc % 4);\n        } else {\n            bc += 4;\n        }\n        let mut ptr = bc as usize;\n\n        let default_byte = [codes[ptr], codes[ptr + 1], codes[ptr + 2], codes[ptr + 3]];\n        let default_byte = u32::from_be_bytes(default_byte);\n        let count = [\n            codes[ptr + 4],\n            codes[ptr + 5],\n            codes[ptr + 6],\n            codes[ptr + 7],\n        ];\n        let count = u32::from_be_bytes(count);\n        ptr += 8;\n\n        let mut jump_table: HashMap<u32, u32> = HashMap::new();\n        for i in 0..count {\n            let value = [codes[ptr], codes[ptr + 1], codes[ptr + 2], codes[ptr + 3]];\n            let value = u32::from_be_bytes(value);\n            let position = [\n                codes[ptr + 4],\n                codes[ptr + 5],\n                codes[ptr + 6],\n                codes[ptr + 7],\n            ];\n            let position = u32::from_be_bytes(position) + origin_bc as u32;\n            ptr += 8;\n            jump_table.insert(value, position);\n        }\n\n        let top_value = {\n            let mut stack = self.frame.area.stack.borrow_mut();\n            stack.pop_int()\n        };\n        match jump_table.get(&(top_value as u32)) {\n            Some(position) => self.goto_abs_with_occupied(*position as i32, 1),\n            None => self.goto_abs_with_occupied(default_byte as i32 + origin_bc, 1),\n        }\n    }\n\n    #[inline]\n    fn ireturn(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v = stack.pop_int();\n        let v = Oop::new_int(v);\n        drop(stack);\n\n        self.set_return(Some(v));\n    }\n\n    #[inline]\n    fn lreturn(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v = stack.pop_long();\n        let v = Oop::new_long(v);\n        drop(stack);\n\n        self.set_return(Some(v));\n    }\n\n    #[inline]\n    fn freturn(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v = stack.pop_float();\n        let v = Oop::new_float(v);\n        drop(stack);\n\n        self.set_return(Some(v));\n    }\n\n    #[inline]\n    fn dreturn(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v = stack.pop_double();\n        let v = Oop::new_double(v);\n        drop(stack);\n\n        self.set_return(Some(v));\n    }\n\n    #[inline]\n    fn areturn(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v = stack.pop_ref();\n        drop(stack);\n\n        self.set_return(Some(v));\n    }\n\n    #[inline]\n    fn return_void(&self) {\n        self.set_return(None);\n    }\n\n    #[inline]\n    fn get_static(&self) {\n        let pc = &self.frame.pc;\n        let codes = &self.code;\n        let cp_idx = read_u2!(pc, codes);\n        self.get_field_helper(Oop::Null, cp_idx, true);\n    }\n\n    #[inline]\n    fn put_static(&self) {\n        let pc = &self.frame.pc;\n        let codes = &self.code;\n        let cp_idx = read_u2!(pc, codes);\n        self.put_field_helper(cp_idx, true);\n    }\n\n    #[inline]\n    fn get_field(&self) {\n        let pc = &self.frame.pc;\n        let codes = &self.code;\n        let idx = read_u2!(pc, codes);\n\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let rf = stack.pop_ref();\n        drop(stack);\n\n        match rf {\n            Oop::Null => {\n                exception::meet_ex(cls_const::J_NPE, None);\n            }\n            _ => {\n                self.get_field_helper(rf, idx, false);\n            }\n        }\n    }\n\n    #[inline]\n    fn put_field(&self) {\n        let pc = &self.frame.pc;\n        let codes = &self.code;\n        let idx = read_u2!(pc, codes);\n        self.put_field_helper(idx, false);\n    }\n\n    #[inline]\n    fn invoke_virtual(&self) {\n        let pc = &self.frame.pc;\n        let codes = &self.code;\n        let idx = read_u2!(pc, codes);\n        self.invoke_helper(false, idx, false);\n    }\n\n    #[inline]\n    fn invoke_special(&self) {\n        let pc = &self.frame.pc;\n        let codes = &self.code;\n        let idx = read_u2!(pc, codes);\n        self.invoke_helper(false, idx, true);\n    }\n\n    #[inline]\n    fn invoke_static(&self) {\n        let pc = &self.frame.pc;\n        let codes = &self.code;\n        let idx = read_u2!(pc, codes);\n        self.invoke_helper(true, idx, true);\n    }\n\n    #[inline]\n    fn invoke_interface(&self) {\n        let pc = &self.frame.pc;\n        let codes = &self.code;\n        let cp_idx = read_u2!(pc, codes);\n        let _count = read_u1!(pc, codes);\n        let zero = read_u1!(pc, codes);\n        if zero != 0 {\n            warn!(\"interpreter: invalid invokeinterface: the value of the fourth operand byte must always be zero.\");\n        }\n\n        self.invoke_helper(false, cp_idx, false);\n    }\n\n    #[inline]\n    fn invoke_dynamic(&self) {\n        //todo: impl\n        unimplemented!()\n    }\n\n    #[inline]\n    fn new_(&self) {\n        let pc = &self.frame.pc;\n        let codes = &self.code;\n        let idx = read_u2!(pc, codes);\n\n        let class = {\n            match runtime::require_class2(idx as u16, &self.cp) {\n                Some(class) => {\n                    oop::class::init_class(&class);\n                    oop::class::init_class_fully(&class);\n\n                    class\n                }\n                None => unreachable!(\"Cannot get class info from constant pool\"),\n            }\n        };\n\n        let v = oop::Oop::new_inst(class);\n        let mut stack = self.frame.area.stack.borrow_mut();\n        stack.push_ref(v, false);\n    }\n\n    #[inline]\n    fn new_array(&self) {\n        let pc = &self.frame.pc;\n        let codes = &self.code;\n        let ary_type = read_byte!(pc, codes);\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let len = stack.pop_int();\n        if len < 0 {\n            drop(stack);\n            exception::meet_ex(cls_const::J_NASE, Some(\"length < 0\".to_string()));\n        } else {\n            let len = len as usize;\n            let ary = Oop::new_type_ary(ary_type, len);\n            stack.push_ref(ary, false);\n        }\n    }\n\n    #[inline]\n    fn anew_array(&self) {\n        let pc = &self.frame.pc;\n        let codes = &self.code;\n        let cp_idx = read_i2!(pc, codes);\n\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let length = stack.pop_int();\n        drop(stack);\n\n        //        info!(\"anew_array length={}\", length);\n        if length < 0 {\n            exception::meet_ex(cls_const::J_NASE, Some(\"length < 0\".to_string()));\n        } else {\n            let class = match runtime::require_class2(cp_idx as u16, &self.cp) {\n                Some(class) => class,\n                None => panic!(\"Cannot get class info from constant pool\"),\n            };\n\n            oop::class::init_class(&class);\n            oop::class::init_class_fully(&class);\n\n            let (name, cl) = {\n                let class = class.get_class();\n                let t = class.get_class_kind_type();\n                let name = match t {\n                    oop::class::ClassKindType::Instance | oop::class::ClassKindType::ObjectAry => {\n                        let mut v = Vec::with_capacity(class.name.len() + 3);\n                        v.push(b'[');\n                        v.push(b'L');\n                        v.extend_from_slice(class.name.as_slice());\n                        v.push(b';');\n\n                        v\n                    }\n                    oop::class::ClassKindType::TypAry => {\n                        let mut v = Vec::with_capacity(class.name.len() + 1);\n                        v.push(b'[');\n                        v.extend_from_slice(class.name.as_slice());\n\n                        v\n                    }\n                };\n\n                let name = Arc::new(name);\n                (name, class.class_loader)\n            };\n\n            trace!(\"anew_array name={}\", unsafe {\n                std::str::from_utf8_unchecked(name.as_slice())\n            });\n            match runtime::require_class(cl, &name) {\n                Some(ary_cls_obj) => {\n                    oop::class::init_class(&ary_cls_obj);\n                    oop::class::init_class_fully(&ary_cls_obj);\n\n                    let ary = Oop::new_ref_ary(ary_cls_obj, length as usize);\n                    let mut stack = self.frame.area.stack.borrow_mut();\n                    stack.push_ref(ary, false);\n                }\n                None => unreachable!(),\n            }\n        }\n    }\n\n    #[inline]\n    fn array_length(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v = stack.pop_ref();\n\n        match v {\n            Oop::Null => {\n                drop(stack);\n                exception::meet_ex(cls_const::J_NPE, None)\n            }\n            Oop::Ref(rf) => {\n                let v = rf.get_raw_ptr();\n                unsafe {\n                    match &(*v).v {\n                        oop::RefKind::Array(ary) => {\n                            let len = ary.elements.len();\n                            stack.push_int(len as i32);\n                        }\n                        oop::RefKind::TypeArray(ary) => {\n                            let len = ary.len();\n                            stack.push_int(len as i32);\n                        }\n                        _ => unreachable!(),\n                    }\n                }\n            }\n            _ => unreachable!(),\n        }\n    }\n\n    #[inline]\n    fn athrow(&self, jt: JavaThreadRef) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let ex = stack.pop_ref();\n        drop(stack);\n\n        jt.write().unwrap().set_ex(ex);\n    }\n\n    #[inline]\n    fn check_cast(&self) {\n        self.check_cast_helper(true);\n    }\n\n    #[inline]\n    fn instance_of(&self) {\n        self.check_cast_helper(false);\n    }\n\n    #[inline]\n    fn monitor_enter(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v = stack.pop_ref();\n        drop(stack);\n\n        match v {\n            Oop::Null => {\n                exception::meet_ex(cls_const::J_NPE, None);\n            }\n            Oop::Ref(v) => v.monitor_enter(),\n            _ => unreachable!(),\n        }\n    }\n\n    #[inline]\n    fn monitor_exit(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let mut v = stack.pop_ref();\n        drop(stack);\n\n        match v {\n            Oop::Null => {\n                exception::meet_ex(cls_const::J_NPE, None);\n            }\n            Oop::Ref(v) => v.monitor_exit(),\n            _ => unreachable!(),\n        }\n    }\n\n    #[inline]\n    fn wide(&mut self) {\n        self.op_widen = true;\n    }\n\n    #[inline]\n    fn multi_anew_array(&self) {\n        let pc = &self.frame.pc;\n        let codes = &self.code;\n        let cp_idx = read_u2!(pc, codes);\n        let dimension = read_u1!(pc, codes);\n\n        let mut lens = Vec::new();\n        let mut stack = self.frame.area.stack.borrow_mut();\n        for _ in 0..dimension {\n            let sub = stack.pop_int();\n            //todo: check java/lang/NegativeArraySizeException\n            lens.push(sub);\n        }\n        drop(stack);\n\n        let cls = require_class2(cp_idx as u16, &self.cp).unwrap();\n        let ary = new_multi_object_array_helper(cls, &lens, 0);\n\n        let mut stack = self.frame.area.stack.borrow_mut();\n        stack.push_ref(ary, false);\n    }\n\n    #[inline]\n    fn if_null(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v = stack.pop_ref();\n\n        match v {\n            Oop::Null => {\n                drop(stack);\n                self.goto_by_offset_hardcoded(2)\n            }\n            _ => {\n                let pc = &self.frame.pc;\n                let _ = pc.fetch_add(2, Ordering::Relaxed);\n            }\n        }\n    }\n\n    #[inline]\n    fn if_non_null(&self) {\n        let mut stack = self.frame.area.stack.borrow_mut();\n        let v = stack.pop_ref();\n\n        match v {\n            Oop::Null => {\n                let pc = &self.frame.pc;\n                let _ = pc.fetch_add(2, Ordering::Relaxed);\n            }\n            _ => {\n                drop(stack);\n                self.goto_by_offset_hardcoded(2)\n            }\n        }\n    }\n\n    #[inline]\n    fn goto_w(&self) {\n        let pc = &self.frame.pc;\n        let _ = pc.fetch_add(4, Ordering::Relaxed);\n        panic!(\"Use of deprecated instruction goto_w, please check your Java compiler\")\n    }\n\n    #[inline]\n    fn jsr_w(&self) {\n        let pc = &self.frame.pc;\n        let _ = pc.fetch_add(4, Ordering::Relaxed);\n        panic!(\"Use of deprecated instruction jsr_w, please check your Java compiler\")\n    }\n\n    #[inline]\n    fn other_wise(&self) {\n        let pc = &self.frame.pc;\n        let codes = &self.frame.code;\n        let pc = pc.load(Ordering::Relaxed);\n        let pc = pc - 1;\n        panic!(\n            \"Use of undefined bytecode: {} at {}\",\n            codes[pc as usize], pc\n        );\n    }\n}\n\nfn new_multi_object_array_helper(cls: ClassRef, lens: &[i32], idx: usize) -> Oop {\n    let length = lens[idx] as usize;\n\n    let down_type = {\n        let cls = cls.get_class();\n        match &cls.kind {\n            oop::ClassKind::Instance(_) => unreachable!(),\n            ClassKind::ObjectArray(obj_ary) => obj_ary.down_type.clone().unwrap(),\n            ClassKind::TypeArray(typ_ary) => typ_ary.down_type.clone().unwrap(),\n        }\n    };\n\n    if idx < lens.len() - 1 {\n        let mut elms = Vec::with_capacity(length);\n        for i in 0..length {\n            let e = new_multi_object_array_helper(down_type.clone(), lens, idx + 1);\n            elms.push(e);\n        }\n\n        Oop::new_ref_ary2(cls, elms)\n    } else {\n        Oop::new_ref_ary(cls, length)\n    }\n}\n"
  },
  {
    "path": "crates/vm/src/runtime/invoke.rs",
    "content": "use crate::native;\nuse crate::native::JNINativeMethodStruct;\nuse crate::oop::{self, Oop, ValueType};\nuse crate::runtime::local::Local;\nuse crate::runtime::{self, exception, frame::Frame, thread, DataArea, Interp};\nuse crate::types::{ClassRef, FrameRef, JavaThreadRef, MethodIdRef};\nuse crate::util;\nuse class_parser::MethodSignature;\nuse classfile::{consts as cls_const, BytesRef, SignatureType};\nuse std::borrow::BorrowMut;\nuse std::cell::RefCell;\nuse std::sync::{Arc, Mutex};\n\npub struct JavaCall {\n    pub mir: MethodIdRef,\n    pub args: Vec<Oop>,\n    pub is_return_void: bool,\n}\n\npub fn invoke_ctor(cls: ClassRef, desc: BytesRef, args: Vec<Oop>) {\n    let ctor = {\n        let cls = cls.get_class();\n        cls.get_this_class_method(&util::S_INIT, &desc).unwrap()\n    };\n\n    let mut jc = JavaCall::new_with_args(ctor, args);\n    jc.invoke(None, false);\n}\n\nimpl JavaCall {\n    pub fn new_with_args(mir: MethodIdRef, args: Vec<Oop>) -> Self {\n        let is_return_void = mir.method.signature.retype == SignatureType::Void;\n        Self {\n            mir,\n            args,\n            is_return_void,\n        }\n    }\n\n    pub fn new(caller: &DataArea, mir: MethodIdRef) -> Result<JavaCall, ()> {\n        let mut args = build_args_from_caller_stack(&caller, &mir.method.signature);\n\n        //insert 'this' value\n        let has_this = !mir.method.is_static();\n        if has_this {\n            let this = {\n                let mut stack = caller.stack.borrow_mut();\n                stack.pop_ref()\n            };\n\n            //check NPE\n            if let Oop::Null = this {\n                let cls_name = {\n                    let cls = mir.method.class.get_class();\n                    cls.name.clone()\n                };\n\n                error!(\"Java new failed, null this: {:?}\", mir.method);\n\n                //Fail fast, avoid a lot of logs, and it is not easy to locate the problem\n                //                        panic!();\n\n                let jt = runtime::thread::current_java_thread();\n                let ex = exception::new(cls_const::J_NPE, None);\n                let mut jt = jt.write().unwrap();\n                jt.set_ex(ex);\n                return Err(());\n            }\n\n            args.insert(0, this);\n        }\n\n        Ok(Self::new_with_args(mir, args))\n    }\n}\n\nimpl JavaCall {\n    //the 'caller' for store return value\n    pub fn invoke(&mut self, caller: Option<&DataArea>, force_no_resolve: bool) {\n        /*\n        Do resolve again first, because you can override in a native way such as:\n        UnixFileSystem override FileSystem\n            public abstract boolean checkAccess(File f, int access);\n\n            public native boolean checkAccess(File f, int access);\n        */\n        self.resolve_virtual_method(force_no_resolve);\n        self.debug();\n\n        if self.mir.method.is_native() {\n            self.invoke_native(caller);\n        } else {\n            self.invoke_java(caller);\n        }\n\n        let jt = runtime::thread::current_java_thread();\n        let _ = jt.write().unwrap().frames.pop();\n    }\n}\n\nimpl JavaCall {\n    fn invoke_java(&mut self, caller: Option<&DataArea>) {\n        self.prepare_sync();\n\n        let jt = runtime::thread::current_java_thread();\n        match self.prepare_frame() {\n            Ok(frame) => {\n                {\n                    jt.write().unwrap().frames.push(frame.clone());\n                }\n\n                let local = self.build_local();\n                let frame_h = frame.try_read().unwrap();\n                let mut interp = Interp::new(frame_h, local);\n                interp.run();\n\n                //if return void, not need set return value\n                if !self.is_return_void && !thread::is_meet_ex() {\n                    let return_v = {\n                        let frame = frame.try_read().unwrap();\n                        let area = frame.area.return_v.borrow();\n                        area.clone()\n                    };\n\n                    let caller = caller.unwrap();\n                    let return_v = return_v.unwrap();\n                    set_return(caller, &self.mir.method.signature.retype, return_v);\n                }\n            }\n\n            Err(ex) => {\n                jt.write().unwrap().set_ex(ex);\n            }\n        }\n\n        self.fin_sync();\n    }\n\n    fn invoke_native(&mut self, caller: Option<&DataArea>) {\n        self.prepare_sync();\n\n        let jt = runtime::thread::current_java_thread();\n        let v = match self.prepare_frame() {\n            Ok(frame) => {\n                {\n                    jt.write().unwrap().frames.push(frame);\n                }\n                match &self.mir.native_impl {\n                    Some(method) => {\n                        let class = self.mir.method.class.clone();\n                        let env = native::new_jni_env(class);\n                        method.invoke(env, &self.args)\n                    }\n                    None => {\n                        let package = self.mir.method.class.get_class().name.as_slice();\n                        let desc = self.mir.method.desc.as_slice();\n                        let name = self.mir.method.name.as_slice();\n                        panic!(\n                            \"Native method not found: {}:{}:{}\",\n                            unsafe { std::str::from_utf8_unchecked(package) },\n                            unsafe { std::str::from_utf8_unchecked(name) },\n                            unsafe { std::str::from_utf8_unchecked(desc) },\n                        )\n                    }\n                }\n            }\n            Err(ex) => Err(ex),\n        };\n\n        match v {\n            Ok(v) => {\n                if !self.is_return_void && !thread::is_meet_ex() {\n                    let caller = caller.unwrap();\n                    let return_v = v.unwrap();\n                    set_return(caller, &self.mir.method.signature.retype, return_v);\n                }\n            }\n            Err(ex) => jt.write().unwrap().set_ex(ex),\n        }\n\n        self.fin_sync();\n    }\n\n    fn prepare_sync(&mut self) {\n        if self.mir.method.is_synchronized() {\n            if self.mir.method.is_static() {\n                let class = self.mir.method.class.get_class();\n                class.monitor_enter();\n            } else {\n                let v = self.args.first().unwrap();\n                let v = v.extract_ref();\n                v.monitor_enter();\n            }\n        }\n    }\n\n    fn fin_sync(&mut self) {\n        if self.mir.method.is_synchronized() {\n            if self.mir.method.is_static() {\n                let class = self.mir.method.class.get_class();\n                class.monitor_exit();\n            } else {\n                let v = self.args.first().unwrap();\n                let v = v.extract_ref();\n                v.monitor_exit();\n            }\n        }\n    }\n\n    fn prepare_frame(&mut self) -> Result<FrameRef, Oop> {\n        let jt = runtime::thread::current_java_thread();\n        let frame_len = { jt.read().unwrap().frames.len() };\n        if frame_len >= runtime::consts::THREAD_MAX_STACK_FRAMES {\n            let ex = exception::new(cls_const::J_SOE, None);\n            return Err(ex);\n        }\n\n        let frame_id = frame_len + 1;\n        let frame = Frame::new(self.mir.clone(), frame_id);\n        let frame_ref = new_sync_ref!(frame);\n        Ok(frame_ref)\n    }\n\n    fn build_local(&self) -> Local {\n        //JVM spec, 2.6.1\n        let max_locals = self.mir.method.get_max_locals();\n        let mut local = Local::new(max_locals);\n        let mut slot_pos: usize = 0;\n        for v in self.args.iter() {\n            let step = match v {\n                Oop::Int(v) => {\n                    local.set_int(slot_pos, *v);\n                    1\n                }\n                Oop::Float(v) => {\n                    local.set_float(slot_pos, *v);\n                    1\n                }\n                Oop::Double(v) => {\n                    local.set_double(slot_pos, *v);\n                    2\n                }\n                Oop::Long((v)) => {\n                    local.set_long(slot_pos, *v);\n                    2\n                }\n                _ => {\n                    local.set_ref(slot_pos, v.clone());\n                    1\n                }\n            };\n\n            slot_pos += step;\n        }\n\n        local\n    }\n\n    fn resolve_virtual_method(&mut self, force_no_resolve: bool) {\n        let resolve_again = if force_no_resolve {\n            false\n        } else {\n            //todo: why is the value of 0 possible in acc_flags?\n            /*\n            This situation occurs when:\n            java/util/regex/Matcher.java\n            bool search(int from)\n              boolean result = parentPattern.root.match(this, from, text);\n\n            The acc_flags of the match method is 0, and what is found is java/util/regex/Patter$Node#match，\n            Correct should use java/util/regex/Patter$Start#match\n            */\n            self.mir.method.is_abstract()\n                || (self.mir.method.is_public() && !self.mir.method.is_final())\n                || (self.mir.method.is_protected() && !self.mir.method.is_final())\n                || (self.mir.method.acc_flags == 0)\n        };\n        trace!(\n            \"resolve_virtual_method resolve_again={}, acc_flags = {}\",\n            resolve_again,\n            self.mir.method.acc_flags\n        );\n        if resolve_again {\n            let this = self.args.get(0).unwrap();\n            let rf = this.extract_ref();\n            let ptr = rf.get_raw_ptr();\n            unsafe {\n                if let oop::RefKind::Inst(inst) = &(*ptr).v {\n                    let name = self.mir.method.name.clone();\n                    let desc = self.mir.method.desc.clone();\n                    let cls = inst.class.get_class();\n                    match cls.get_virtual_method(&name, &desc) {\n                        Ok(mir) => self.mir = mir,\n                        _ => {\n                            let cls = self.mir.method.class.get_class();\n                            warn!(\n                                \"resolve again failed, {}:{}:{}, acc_flags = {}\",\n                                String::from_utf8_lossy(cls.name.as_slice()),\n                                String::from_utf8_lossy(name.as_slice()),\n                                String::from_utf8_lossy(desc.as_slice()),\n                                self.mir.method.acc_flags\n                            );\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    fn debug(&self) {\n        info!(\n            \"invoke method = {:?}, static={} native={} sync={}\",\n            self.mir.method,\n            self.mir.method.is_static(),\n            self.mir.method.is_native(),\n            self.mir.method.is_synchronized()\n        );\n    }\n}\n\nfn build_args_from_caller_stack(caller: &DataArea, sig: &MethodSignature) -> Vec<Oop> {\n    let mut caller = caller.stack.borrow_mut();\n    let mut args = Vec::with_capacity(sig.args.len() + 1);\n\n    //build args from caller's stack, so should rev the signature args\n    for it in sig.args.iter().rev() {\n        let v = match it {\n            SignatureType::Byte\n            | SignatureType::Boolean\n            | SignatureType::Int\n            | SignatureType::Char\n            | SignatureType::Short => {\n                let v = caller.pop_int();\n                Oop::new_int(v)\n            }\n            SignatureType::Long => {\n                let v = caller.pop_long();\n                Oop::new_long(v)\n            }\n            SignatureType::Float => {\n                let v = caller.pop_float();\n                Oop::new_float(v)\n            }\n            SignatureType::Double => {\n                let v = caller.pop_double();\n                Oop::new_double(v)\n            }\n            SignatureType::Object(_, _, _) | SignatureType::Array(_) => caller.pop_ref(),\n            t => unreachable!(\"t = {:?}\", t),\n        };\n\n        args.push(v);\n    }\n\n    //the args built from caller's stack, should reverse args\n    args.reverse();\n\n    args\n}\n\npub fn set_return(caller: &DataArea, return_type: &SignatureType, v: Oop) {\n    let with_nop = match return_type {\n        SignatureType::Double | SignatureType::Long => true,\n        _ => false,\n    };\n    let mut stack = caller.stack.borrow_mut();\n    stack.push_ref(v, with_nop);\n}\n"
  },
  {
    "path": "crates/vm/src/runtime/local.rs",
    "content": "use crate::oop::{Oop, OopPtr};\nuse crate::runtime::Slot;\nuse crate::util;\n\npub struct Local {\n    locals: Vec<Slot>,\n}\n\nimpl Local {\n    pub fn new(size: usize) -> Self {\n        let size = size + 1;\n        let locals = vec![Slot::Nop; size];\n        Self { locals }\n    }\n\n    #[inline]\n    pub fn set_int(&mut self, pos: usize, v: i32) {\n        self.locals[pos] = Slot::I32(v);\n    }\n\n    #[inline]\n    pub fn set_long(&mut self, pos: usize, v: i64) {\n        self.locals[pos] = Slot::I64(v);\n    }\n\n    #[inline]\n    pub fn set_float(&mut self, pos: usize, v: f32) {\n        self.locals[pos] = Slot::F32(v);\n    }\n\n    #[inline]\n    pub fn set_double(&mut self, pos: usize, v: f64) {\n        self.locals[pos] = Slot::F64(v);\n    }\n\n    #[inline]\n    pub fn set_ref(&mut self, pos: usize, v: Oop) {\n        self.locals[pos] = Slot::Ref(v);\n    }\n\n    #[inline]\n    pub fn get_int(&self, pos: usize) -> i32 {\n        match self.locals.get(pos).unwrap() {\n            Slot::I32(v) => *v,\n            Slot::Ref(v) => OopPtr::java_lang_integer_value(v.extract_ref()),\n            t => panic!(\"Illegal type {:?}\", t),\n        }\n    }\n\n    #[inline]\n    pub fn get_long(&self, pos: usize) -> i64 {\n        if let Slot::I64(v) = self.locals.get(pos).unwrap() {\n            *v\n        } else {\n            panic!(\"Illegal type\");\n        }\n    }\n\n    #[inline]\n    pub fn get_float(&self, pos: usize) -> f32 {\n        if let Slot::F32(v) = self.locals.get(pos).unwrap() {\n            *v\n        } else {\n            panic!(\"Illegal type\");\n        }\n    }\n\n    #[inline]\n    pub fn get_double(&self, pos: usize) -> f64 {\n        if let Slot::F64(v) = self.locals.get(pos).unwrap() {\n            *v\n        } else {\n            panic!(\"Illegal type\");\n        }\n    }\n\n    #[inline]\n    pub fn get_ref(&self, pos: usize) -> Oop {\n        match self.locals.get(pos) {\n            Some(Slot::Ref(v)) => v.clone(),\n            t => panic!(\"Illegal type = {:?}\", t),\n        }\n    }\n}\n"
  },
  {
    "path": "crates/vm/src/runtime/method.rs",
    "content": "use crate::native::JNINativeMethod;\nuse crate::oop::{self, ValueType};\nuse crate::runtime::local::Local;\nuse crate::runtime::stack::Stack;\nuse crate::runtime::{self, require_class2};\nuse crate::types::ClassRef;\nuse crate::types::*;\nuse crate::util::PATH_SEP;\nuse crate::{native, util};\nuse class_parser::MethodSignature;\nuse classfile::{\n    attributes::Code, attributes::LineNumber, constant_pool, consts, flags::*, AttributeType,\n    BytesRef, ConstantPool, FieldInfo, MethodInfo, U2,\n};\nuse std::fmt;\nuse std::fmt::Formatter;\nuse std::ops::Deref;\nuse std::sync::Arc;\n\npub fn get_method_ref(cp: &ConstantPool, idx: usize) -> Result<MethodIdRef, ()> {\n    let (tag, class_index, name_and_type_index) = constant_pool::get_method_ref(cp, idx);\n\n    //load Method's Class, then init it\n    let class = require_class2(class_index, cp).unwrap_or_else(|| {\n        panic!(\n            \"Unknown method class {:?}\",\n            cp.get(class_index as usize)\n                .expect(\"Missing item\")\n                .as_cp_item(cp)\n        )\n    });\n\n    oop::class::init_class(&class);\n    oop::class::init_class_fully(&class);\n\n    let (name, desc) = constant_pool::get_name_and_type(cp, name_and_type_index as usize);\n    let class = class.get_class();\n\n    trace!(\n        \"get_method_ref cls={}, name={}, desc={}\",\n        unsafe { std::str::from_utf8_unchecked(class.name.as_slice()) },\n        unsafe { std::str::from_utf8_unchecked(name.as_slice()) },\n        unsafe { std::str::from_utf8_unchecked(desc.as_slice()) },\n    );\n    if tag == consts::CONSTANT_METHOD_REF_TAG {\n        // invokespecial, invokestatic and invokevirtual\n        class.get_class_method(name, desc)\n    } else {\n        // invokeinterface\n        class.get_interface_method(name, desc)\n    }\n}\n\n#[derive(Clone)]\npub struct MethodId {\n    pub offset: usize,\n    pub method: Method,\n    pub native_impl: Option<JNINativeMethod>,\n}\n\nimpl MethodId {\n    pub fn new(offset: usize, method: Method) -> Arc<Self> {\n        let native_impl = if method.is_native() {\n            let package = method.class.get_class().name.as_slice();\n            let desc = method.desc.as_slice();\n            let name = method.name.as_slice();\n            native::find_symbol(package, name, desc)\n        } else {\n            None\n        };\n\n        Arc::new(Self {\n            offset,\n            method,\n            native_impl,\n        })\n    }\n}\n\n#[derive(Clone)]\npub struct Method {\n    pub class: ClassRef,\n    pub class_file: ClassFileRef,\n    pub cls_name: BytesRef,\n    pub name: BytesRef,\n    pub desc: BytesRef,\n    pub acc_flags: U2,\n    pub signature: MethodSignature,\n\n    pub code: Option<Code>,\n    pub line_num_table: Vec<LineNumber>,\n\n    method_info_index: usize,\n}\n\nimpl Method {\n    pub fn new(\n        cp: &ConstantPool,\n        mi: &MethodInfo,\n        class: ClassRef,\n        class_file: ClassFileRef,\n        method_info_index: usize,\n        cls_name: BytesRef,\n    ) -> Self {\n        let name = constant_pool::get_utf8(cp, mi.name_index as usize).clone();\n        let desc = constant_pool::get_utf8(cp, mi.desc_index as usize).clone();\n        let acc_flags = mi.acc_flags;\n        let signature = MethodSignature::new(desc.as_slice());\n        let code = mi.get_code();\n        let line_num_table = mi.get_line_number_table();\n\n        Self {\n            class,\n            class_file,\n            cls_name,\n            name,\n            desc,\n            acc_flags,\n            signature,\n            code,\n            line_num_table,\n            method_info_index,\n        }\n    }\n\n    pub fn get_max_locals(&self) -> usize {\n        match &self.code {\n            Some(code) => code.max_locals as usize,\n            None => 0,\n        }\n    }\n\n    pub fn get_max_stack(&self) -> usize {\n        match &self.code {\n            Some(code) => code.max_stack as usize,\n            None => 0,\n        }\n    }\n\n    pub fn build_local(&self) -> Local {\n        let max_locals = self.get_max_locals();\n        Local::new(max_locals)\n    }\n\n    pub fn build_stack(&self) -> Stack {\n        let max_stack = self.get_max_stack();\n        Stack::new(max_stack)\n    }\n\n    pub fn find_exception_handler(&self, cp: &ConstantPool, pc: U2, ex: ClassRef) -> Option<U2> {\n        if let Some(code) = &self.code {\n            for e in code.exceptions.iter() {\n                if e.contains(pc) {\n                    if e.is_finally() {\n                        return Some(e.handler_pc);\n                    }\n\n                    if let Some(class) = runtime::require_class2(e.catch_type, cp) {\n                        if runtime::cmp::instance_of(ex.clone(), class) {\n                            return Some(e.handler_pc);\n                        }\n                    }\n                }\n            }\n        }\n\n        None\n    }\n\n    pub fn get_line_num(&self, pc: U2) -> i32 {\n        let mut best_bci = 0;\n        let mut best_line = -1;\n\n        for it in self.line_num_table.iter() {\n            if it.start_pc == pc {\n                return it.number as i32;\n            } else if it.start_pc < pc && it.start_pc >= best_bci {\n                best_bci = it.start_pc;\n                best_line = it.number as i32;\n            }\n        }\n\n        best_line\n    }\n\n    pub fn get_annotation(&self) -> Option<Vec<u8>> {\n        let method_info = self.class_file.methods.get(self.method_info_index).unwrap();\n        util::attributes::assemble_annotation(&method_info.attrs)\n    }\n\n    pub fn get_param_annotation(&self) -> Option<Vec<u8>> {\n        let method_info = self.class_file.methods.get(self.method_info_index).unwrap();\n        util::attributes::assemble_param_annotation(&method_info.attrs)\n    }\n\n    pub fn get_type_annotation(&self) -> Option<Vec<u8>> {\n        let method_info = self.class_file.methods.get(self.method_info_index).unwrap();\n        util::attributes::assemble_type_annotation(&method_info.attrs)\n    }\n\n    pub fn get_annotation_default(&self) -> Option<Vec<u8>> {\n        let method_info = self.class_file.methods.get(self.method_info_index).unwrap();\n        util::attributes::assemble_annotation_default(&method_info.attrs)\n    }\n\n    pub fn check_annotation(&self, name: &[u8]) -> bool {\n        let method_info = self.class_file.methods.get(self.method_info_index).unwrap();\n\n        for it in method_info.attrs.iter() {\n            if let AttributeType::RuntimeVisibleAnnotations { raw, annotations } = it {\n                for it in annotations.iter() {\n                    if it.type_name.as_slice() == name {\n                        return true;\n                    }\n                }\n            }\n        }\n\n        false\n    }\n\n    pub fn is_public(&self) -> bool {\n        self.acc_flags & ACC_PUBLIC != 0\n    }\n\n    pub fn is_private(&self) -> bool {\n        self.acc_flags & ACC_PRIVATE != 0\n    }\n\n    pub fn is_protected(&self) -> bool {\n        self.acc_flags & ACC_PROTECTED != 0\n    }\n\n    pub fn is_final(&self) -> bool {\n        self.acc_flags & ACC_FINAL != 0\n    }\n\n    pub fn is_static(&self) -> bool {\n        self.acc_flags & ACC_STATIC != 0\n    }\n\n    pub fn is_synchronized(&self) -> bool {\n        self.acc_flags & ACC_SYNCHRONIZED != 0\n    }\n\n    pub fn is_native(&self) -> bool {\n        self.acc_flags & ACC_NATIVE != 0\n    }\n\n    pub fn is_abstract(&self) -> bool {\n        self.acc_flags & ACC_ABSTRACT != 0\n    }\n\n    pub fn is_interface(&self) -> bool {\n        self.acc_flags & ACC_INTERFACE != 0\n    }\n}\n\nimpl fmt::Debug for MethodId {\n    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {\n        let cls_name = unsafe { std::str::from_utf8_unchecked(self.method.cls_name.as_slice()) };\n        let name = unsafe { std::str::from_utf8_unchecked(self.method.name.as_slice()) };\n        let desc = unsafe { std::str::from_utf8_unchecked(self.method.desc.as_slice()) };\n        write!(\n            f,\n            \"{}:{}:{}, offset = {}\",\n            cls_name, name, desc, self.offset\n        )\n    }\n}\n\nimpl fmt::Debug for Method {\n    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {\n        let cls_name = unsafe { std::str::from_utf8_unchecked(self.cls_name.as_slice()) };\n        let name = unsafe { std::str::from_utf8_unchecked(self.name.as_slice()) };\n        let desc = unsafe { std::str::from_utf8_unchecked(self.desc.as_slice()) };\n        write!(f, \"{}:{}:{}\", cls_name, name, desc)\n    }\n}\n"
  },
  {
    "path": "crates/vm/src/runtime/mod.rs",
    "content": "#![allow(unused)]\n\npub use class_loader::{require_class, require_class2, require_class3, ClassLoader};\npub use class_path_manager::{\n    add_path as add_class_path, add_paths as add_class_paths,\n    find_class as find_class_in_classpath, ClassPathResult,\n};\npub use constant_pool::ConstantPoolCache;\npub use consts::THREAD_MAX_STACK_FRAMES;\npub use dataarea::DataArea;\npub use frame::Frame;\npub use interp::Interp;\npub use invoke::JavaCall;\npub use slot::Slot;\npub use sys_dic::{find as sys_dic_find, put as sys_dic_put};\npub use thread::JavaThread;\n\nmod class_loader;\nmod class_path_manager;\npub mod cmp;\nmod constant_pool;\nmod consts;\nmod dataarea;\npub mod exception;\nmod frame;\nmod init_vm;\npub mod interp;\npub mod invoke;\nmod local;\npub mod method;\nmod slot;\nmod stack;\nmod sys_dic;\npub mod thread;\npub mod vm;\n\npub fn init() {\n    sys_dic::init();\n    class_path_manager::init();\n}\n"
  },
  {
    "path": "crates/vm/src/runtime/slot.rs",
    "content": "use crate::oop::Oop;\n\n#[derive(Debug, Clone)]\npub enum Slot {\n    ConstM1,\n    Const0,\n    Const1,\n    Const2,\n    Const3,\n    Const4,\n    Const5,\n    I32(i32),\n    F32(f32),\n    F64(f64),\n    I64(i64),\n    Ref(Oop),\n    Nop, //for Stack long, double\n}\n"
  },
  {
    "path": "crates/vm/src/runtime/stack.rs",
    "content": "use crate::oop::{consts, Oop};\nuse crate::runtime::Slot;\n\n#[derive(Debug)]\npub struct Stack {\n    inner: Vec<Slot>,\n}\n\nimpl Stack {\n    pub fn new(size: usize) -> Self {\n        Self {\n            inner: Vec::with_capacity(size),\n        }\n    }\n\n    #[inline]\n    pub fn push_int(&mut self, v: i32) {\n        self.inner.push(Slot::I32(v));\n    }\n\n    #[inline]\n    pub fn push_int2(&mut self, v: &[u8; 4]) {\n        let v = i32::from_be_bytes(*v);\n        self.inner.push(Slot::I32(v));\n    }\n\n    #[inline]\n    pub fn push_float(&mut self, v: f32) {\n        self.inner.push(Slot::F32(v));\n    }\n\n    #[inline]\n    pub fn push_float2(&mut self, v: &[u8; 4]) {\n        let v = u32::from_be_bytes(*v);\n        let v = f32::from_bits(v);\n        self.inner.push(Slot::F32(v));\n    }\n\n    #[inline]\n    pub fn push_double(&mut self, v: f64) {\n        self.push_nop();\n        self.inner.push(Slot::F64(v));\n    }\n\n    #[inline]\n    pub fn push_double2(&mut self, v: &[u8; 8]) {\n        let v = u64::from_be_bytes(*v);\n        let v = f64::from_bits(v);\n        self.push_double(v);\n    }\n\n    #[inline]\n    pub fn push_long(&mut self, v: i64) {\n        self.push_nop();\n        self.inner.push(Slot::I64(v));\n    }\n\n    #[inline]\n    pub fn push_long2(&mut self, v: &[u8; 8]) {\n        let v = i64::from_be_bytes(*v);\n        self.push_long(v);\n    }\n\n    #[inline]\n    pub fn push_null(&mut self) {\n        self.inner.push(Slot::Ref(Oop::Null));\n    }\n\n    #[inline]\n    pub fn push_const_m1(&mut self) {\n        self.inner.push(Slot::ConstM1);\n    }\n\n    /*\n    double & long, with_nop = true\n    */\n    #[inline]\n    pub fn push_const0(&mut self, with_nop: bool) {\n        if with_nop {\n            self.push_nop();\n        }\n        self.inner.push(Slot::Const0);\n    }\n\n    /*\n       double & long, with_nop = true\n    */\n    #[inline]\n    pub fn push_const1(&mut self, with_nop: bool) {\n        if with_nop {\n            self.push_nop();\n        }\n        self.inner.push(Slot::Const1);\n    }\n\n    #[inline]\n    pub fn push_const2(&mut self) {\n        self.inner.push(Slot::Const2);\n    }\n\n    #[inline]\n    pub fn push_const3(&mut self) {\n        self.inner.push(Slot::Const3);\n    }\n\n    #[inline]\n    pub fn push_const4(&mut self) {\n        self.inner.push(Slot::Const4);\n    }\n\n    #[inline]\n    pub fn push_const5(&mut self) {\n        self.inner.push(Slot::Const5);\n    }\n\n    #[inline]\n    pub fn push_ref(&mut self, v: Oop, with_nop: bool) {\n        if with_nop {\n            self.push_nop();\n        }\n        self.inner.push(Slot::Ref(v));\n    }\n\n    #[inline]\n    pub fn pop_int(&mut self) -> i32 {\n        match self.inner.pop().unwrap() {\n            Slot::ConstM1 => -1,\n            Slot::Const0 => 0,\n            Slot::Const1 => 1,\n            Slot::Const2 => 2,\n            Slot::Const3 => 3,\n            Slot::Const4 => 4,\n            Slot::Const5 => 5,\n            Slot::I32(v) => v,\n            Slot::Ref(v) => v.extract_int(),\n            _ => panic!(\"Illegal type\"),\n        }\n    }\n\n    #[inline]\n    pub fn pop_float(&mut self) -> f32 {\n        match self.inner.pop().unwrap() {\n            Slot::Const0 => 0.0,\n            Slot::Const1 => 1.0,\n            Slot::Const2 => 2.0,\n            Slot::F32(v) => v,\n            Slot::Ref(v) => v.extract_float(),\n            _ => panic!(\"Illegal type\"),\n        }\n    }\n\n    #[inline]\n    pub fn pop_double(&mut self) -> f64 {\n        match self.inner.pop() {\n            Some(v) => {\n                self.pop_nop();\n                match v {\n                    Slot::Const0 => 0.0,\n                    Slot::Const1 => 1.0,\n                    Slot::F64(v) => v,\n                    Slot::Ref(v) => v.extract_double(),\n                    _ => panic!(\"Illegal type\"),\n                }\n            }\n            None => panic!(\"Empty Stack!\"),\n        }\n    }\n\n    #[inline]\n    pub fn pop_long(&mut self) -> i64 {\n        match self.inner.pop() {\n            Some(v) => {\n                self.pop_nop();\n                match v {\n                    Slot::Const0 => 0,\n                    Slot::Const1 => 1,\n                    Slot::I64(v) => v,\n                    Slot::Ref(v) => v.extract_long(),\n                    _ => panic!(\"Illegal type\"),\n                }\n            }\n            _ => panic!(\"Empty Stack!\"),\n        }\n    }\n\n    #[inline]\n    pub fn pop_ref(&mut self) -> Oop {\n        match self.inner.pop() {\n            Some(Slot::Ref(v)) => v,\n            t => panic!(\"Illegal type = {:?}\", t),\n        }\n    }\n\n    #[inline]\n    pub fn drop_top(&mut self) {\n        let _ = self.inner.pop();\n    }\n\n    pub fn clear(&mut self) {\n        self.inner.clear();\n    }\n\n    #[inline]\n    pub fn dup(&mut self) {\n        let v = self.inner.pop().unwrap();\n        self.inner.push(v.clone());\n        self.inner.push(v);\n    }\n\n    #[inline]\n    pub fn dup_x1(&mut self) {\n        let v1 = self.inner.pop().unwrap();\n        let v2 = self.inner.pop().unwrap();\n        self.inner.push(v1.clone());\n        self.inner.push(v2);\n        self.inner.push(v1);\n    }\n\n    #[inline]\n    pub fn dup_x2(&mut self) {\n        let v1 = self.inner.pop().unwrap();\n        let v2 = self.inner.pop().unwrap();\n        let v3 = self.inner.pop().unwrap();\n        self.inner.push(v1.clone());\n        self.inner.push(v3);\n        self.inner.push(v2);\n        self.inner.push(v1);\n    }\n\n    #[inline]\n    pub fn dup2(&mut self) {\n        let v1 = self.inner.pop().unwrap();\n        let v2 = self.inner.pop().unwrap();\n        self.inner.push(v2.clone());\n        self.inner.push(v1.clone());\n        self.inner.push(v2);\n        self.inner.push(v1);\n    }\n\n    #[inline]\n    pub fn dup2_x1(&mut self) {\n        let v1 = self.inner.pop().unwrap();\n        let v2 = self.inner.pop().unwrap();\n        let v3 = self.inner.pop().unwrap();\n        self.inner.push(v2.clone());\n        self.inner.push(v1.clone());\n        self.inner.push(v3);\n        self.inner.push(v2);\n        self.inner.push(v1);\n    }\n\n    #[inline]\n    pub fn dup2_x2(&mut self) {\n        let v1 = self.inner.pop().unwrap();\n        let v2 = self.inner.pop().unwrap();\n        let v3 = self.inner.pop().unwrap();\n        let v4 = self.inner.pop().unwrap();\n        self.inner.push(v2.clone());\n        self.inner.push(v1.clone());\n        self.inner.push(v4);\n        self.inner.push(v3);\n        self.inner.push(v2);\n        self.inner.push(v1);\n    }\n\n    #[inline]\n    pub fn swap(&mut self) {\n        let v1 = self.inner.pop().unwrap();\n        let v2 = self.inner.pop().unwrap();\n        self.inner.push(v1);\n        self.inner.push(v2);\n    }\n}\n\nimpl Stack {\n    fn push_nop(&mut self) {\n        self.inner.push(Slot::Nop);\n    }\n\n    fn pop_nop(&mut self) {\n        match self.inner.pop() {\n            Some(Slot::Nop) => (),\n            _ => panic!(\"Should be Nop!\"),\n        }\n    }\n}\n"
  },
  {
    "path": "crates/vm/src/runtime/sys_dic.rs",
    "content": "use crate::types::ClassRef;\nuse crate::util;\n\nuse rustc_hash::FxHashMap;\nuse std::sync::{Arc, Mutex};\n\ntype SystemDictionary = Mutex<FxHashMap<String, ClassRef>>;\n\nlazy_static! {\n    static ref SYS_DIC: SystemDictionary = { Mutex::new(FxHashMap::default()) };\n}\n\npub fn put(key: &[u8], klass: ClassRef) {\n    debug_assert!(!key.contains(&b'.'));\n\n    let key = Vec::from(key);\n    let key = unsafe { String::from_utf8_unchecked(key) };\n    let mut dict = SYS_DIC.lock().unwrap();\n    dict.insert(key, klass);\n}\n\n//key style: \"sun/security/provider/Sun\"\npub fn find(key: &[u8]) -> Option<ClassRef> {\n    debug_assert!(!key.contains(&b'.'));\n    let key = unsafe { std::str::from_utf8_unchecked(key) };\n    let dict = SYS_DIC.lock().unwrap();\n    dict.get(key).cloned()\n}\n\npub fn init() {\n    lazy_static::initialize(&SYS_DIC);\n}\n"
  },
  {
    "path": "crates/vm/src/runtime/thread/condvar.rs",
    "content": "use crate::runtime::thread::{mutex_raw, ReentrantMutex};\nuse std::cell::UnsafeCell;\nuse std::time::Duration;\n\npub struct Condvar {\n    inner: UnsafeCell<libc::pthread_cond_t>,\n}\n\nunsafe impl Send for Condvar {}\nunsafe impl Sync for Condvar {}\n\nconst TIMESPEC_MAX: libc::timespec = libc::timespec {\n    tv_sec: <libc::time_t>::max_value(),\n    tv_nsec: 1_000_000_000 - 1,\n};\n\nfn saturating_cast_to_time_t(value: u64) -> libc::time_t {\n    if value > <libc::time_t>::max_value() as u64 {\n        <libc::time_t>::max_value()\n    } else {\n        value as libc::time_t\n    }\n}\n\nimpl Condvar {\n    pub const fn new() -> Condvar {\n        // Might be moved and address is changing it is better to avoid\n        // initialization of potentially opaque OS data before it landed\n        Condvar {\n            inner: UnsafeCell::new(libc::PTHREAD_COND_INITIALIZER),\n        }\n    }\n\n    /// # Safety\n    /// todo: This function should really be documented\n    #[cfg(any(\n        target_os = \"macos\",\n        target_os = \"ios\",\n        target_os = \"l4re\",\n        target_os = \"android\",\n        target_os = \"hermit\"\n    ))]\n    pub unsafe fn init(&mut self) {}\n\n    #[cfg(not(any(\n        target_os = \"macos\",\n        target_os = \"ios\",\n        target_os = \"l4re\",\n        target_os = \"android\",\n        target_os = \"hermit\"\n    )))]\n    pub unsafe fn init(&mut self) {\n        use std::mem;\n        let mut attr: libc::pthread_condattr_t = mem::uninitialized();\n        let r = libc::pthread_condattr_init(&mut attr);\n        assert_eq!(r, 0);\n        let r = libc::pthread_condattr_setclock(&mut attr, libc::CLOCK_MONOTONIC);\n        assert_eq!(r, 0);\n        let r = libc::pthread_cond_init(self.inner.get(), &attr);\n        assert_eq!(r, 0);\n        let r = libc::pthread_condattr_destroy(&mut attr);\n        assert_eq!(r, 0);\n    }\n\n    /// # Safety\n    /// todo: This function should really be documented\n    #[inline]\n    pub unsafe fn notify_one(&self) {\n        let r = libc::pthread_cond_signal(self.inner.get());\n        debug_assert_eq!(r, 0);\n    }\n\n    /// # Safety\n    /// todo: This function should really be documented\n    #[inline]\n    pub unsafe fn notify_all(&self) {\n        let r = libc::pthread_cond_broadcast(self.inner.get());\n        debug_assert_eq!(r, 0);\n    }\n\n    /// # Safety\n    /// todo: This function should really be documented\n    #[inline]\n    pub unsafe fn wait(&self, mutex: &ReentrantMutex) {\n        let r = libc::pthread_cond_wait(self.inner.get(), mutex_raw(mutex));\n        debug_assert_eq!(r, 0);\n    }\n\n    // This implementation is used on systems that support pthread_condattr_setclock\n    // where we configure condition variable to use monotonic clock (instead of\n    // default system clock). This approach avoids all problems that result\n    // from changes made to the system time.\n    #[cfg(not(any(\n        target_os = \"macos\",\n        target_os = \"ios\",\n        target_os = \"android\",\n        target_os = \"hermit\"\n    )))]\n    pub unsafe fn wait_timeout(&self, mutex: &ReentrantMutex, dur: Duration) -> bool {\n        use std::mem;\n\n        let mut now: libc::timespec = mem::zeroed();\n        let r = libc::clock_gettime(libc::CLOCK_MONOTONIC, &mut now);\n        assert_eq!(r, 0);\n\n        // Nanosecond calculations can't overflow because both values are below 1e9.\n        let nsec = dur.subsec_nanos() + now.tv_nsec as u32;\n\n        let sec = saturating_cast_to_time_t(dur.as_secs())\n            .checked_add((nsec / 1_000_000_000) as libc::time_t)\n            .and_then(|s| s.checked_add(now.tv_sec));\n        let nsec = nsec % 1_000_000_000;\n\n        let timeout = sec\n            .map(|s| libc::timespec {\n                tv_sec: s,\n                tv_nsec: nsec as _,\n            })\n            .unwrap_or(TIMESPEC_MAX);\n\n        let r = libc::pthread_cond_timedwait(self.inner.get(), mutex_raw(mutex), &timeout);\n        assert!(r == libc::ETIMEDOUT || r == 0);\n        r == 0\n    }\n\n    /// # Safety\n    /// todo: This function should really be documented\n    // This implementation is modeled after libcxx's condition_variable\n    // https://github.com/llvm-mirror/libcxx/blob/release_35/src/condition_variable.cpp#L46\n    // https://github.com/llvm-mirror/libcxx/blob/release_35/include/__mutex_base#L367\n    #[cfg(any(\n        target_os = \"macos\",\n        target_os = \"ios\",\n        target_os = \"android\",\n        target_os = \"hermit\"\n    ))]\n    pub unsafe fn wait_timeout(&self, mutex: &ReentrantMutex, mut dur: Duration) -> bool {\n        use std::ptr;\n        use std::time::Instant;\n\n        // 1000 years\n        let max_dur = Duration::from_secs(1000 * 365 * 86400);\n\n        if dur > max_dur {\n            // OSX implementation of `pthread_cond_timedwait` is buggy\n            // with super long durations. When duration is greater than\n            // 0x100_0000_0000_0000 seconds, `pthread_cond_timedwait`\n            // in macOS Sierra return error 316.\n            //\n            // This program demonstrates the issue:\n            // https://gist.github.com/stepancheg/198db4623a20aad2ad7cddb8fda4a63c\n            //\n            // To work around this issue, and possible bugs of other OSes, timeout\n            // is clamped to 1000 years, which is allowable per the API of `wait_timeout`\n            // because of spurious wakeups.\n\n            dur = max_dur;\n        }\n\n        // First, figure out what time it currently is, in both system and\n        // stable time.  pthread_cond_timedwait uses system time, but we want to\n        // report timeout based on stable time.\n        let mut sys_now = libc::timeval {\n            tv_sec: 0,\n            tv_usec: 0,\n        };\n        let stable_now = Instant::now();\n        let r = libc::gettimeofday(&mut sys_now, ptr::null_mut());\n        debug_assert_eq!(r, 0);\n\n        let nsec = dur.subsec_nanos() as libc::c_long + (sys_now.tv_usec * 1000) as libc::c_long;\n        let extra = (nsec / 1_000_000_000) as libc::time_t;\n        let nsec = nsec % 1_000_000_000;\n        let seconds = saturating_cast_to_time_t(dur.as_secs());\n\n        let timeout = sys_now\n            .tv_sec\n            .checked_add(extra)\n            .and_then(|s| s.checked_add(seconds))\n            .map(|s| libc::timespec {\n                tv_sec: s,\n                tv_nsec: nsec,\n            })\n            .unwrap_or(TIMESPEC_MAX);\n\n        // And wait!\n        let r = libc::pthread_cond_timedwait(self.inner.get(), mutex_raw(mutex), &timeout);\n        debug_assert!(r == libc::ETIMEDOUT || r == 0);\n\n        // ETIMEDOUT is not a totally reliable method of determining timeout due\n        // to clock shifts, so do the check ourselves\n        stable_now.elapsed() < dur\n    }\n\n    /// # Safety\n    /// todo: This function should really be documented\n    #[inline]\n    #[cfg(not(target_os = \"dragonfly\"))]\n    pub unsafe fn destroy(&self) {\n        let r = libc::pthread_cond_destroy(self.inner.get());\n        debug_assert_eq!(r, 0);\n    }\n\n    #[inline]\n    #[cfg(target_os = \"dragonfly\")]\n    pub unsafe fn destroy(&self) {\n        let r = libc::pthread_cond_destroy(self.inner.get());\n        // On DragonFly pthread_cond_destroy() returns EINVAL if called on\n        // a condvar that was just initialized with\n        // libc::PTHREAD_COND_INITIALIZER. Once it is used or\n        // pthread_cond_init() is called, this behaviour no longer occurs.\n        debug_assert!(r == 0 || r == libc::EINVAL);\n    }\n}\n"
  },
  {
    "path": "crates/vm/src/runtime/thread/java_thread.rs",
    "content": "use crate::oop::{self, consts, Oop};\nuse crate::types::{FrameRef, JavaThreadRef};\nuse std::cell::RefCell;\nuse std::sync::atomic::{AtomicBool, Ordering};\nuse std::sync::{Arc, RwLock};\n\nthread_local! {\n    pub static THREAD: RefCell<JavaThreadRef> = RefCell::new(JavaThread::main());\n    pub static IS_MEET_EX: AtomicBool = AtomicBool::new(false);\n}\n\npub fn current_java_thread() -> JavaThreadRef {\n    THREAD.with(|t| t.borrow().clone())\n}\n\n#[inline]\npub fn is_meet_ex() -> bool {\n    IS_MEET_EX.with(|v| v.load(Ordering::Relaxed))\n}\n\n#[inline]\nfn set_meet_ex(val: bool) {\n    IS_MEET_EX.with(|v| v.store(val, Ordering::Relaxed));\n}\n\npub struct JavaThread {\n    pub frames: Vec<FrameRef>,\n    in_safe_point: bool,\n\n    pub java_thread_obj: Option<Oop>,\n    pub ex: Option<Oop>,\n    pub is_alive: bool,\n    pub eetop: i64,\n\n    pub tag: String, //for debug\n}\n\nimpl JavaThread {\n    pub fn new(tag: Option<String>, eetop: i64) -> JavaThreadRef {\n        let tag = tag.unwrap_or_else(|| format!(\"thread-{}\", eetop));\n        let t = Self {\n            frames: Vec::new(),\n            in_safe_point: false,\n\n            java_thread_obj: None,\n            ex: None,\n            is_alive: false,\n            eetop,\n            tag,\n        };\n        Arc::new(RwLock::new(Box::new(t)))\n    }\n\n    pub fn main() -> JavaThreadRef {\n        JavaThread::new(Some(\"main\".to_string()), 0)\n    }\n\n    pub fn set_java_thread_obj(&mut self, obj: Oop) {\n        self.java_thread_obj = Some(obj);\n    }\n}\n\n//exception\nimpl JavaThread {\n    pub fn set_ex(&mut self, ex: Oop) {\n        set_meet_ex(true);\n        self.ex = Some(ex);\n    }\n\n    pub fn take_ex(&mut self) -> Option<Oop> {\n        set_meet_ex(false);\n        self.ex.take()\n    }\n}\n"
  },
  {
    "path": "crates/vm/src/runtime/thread/main.rs",
    "content": "use crate::oop::{self, Class, Oop, OopPtr};\nuse crate::runtime::thread::thread_pool;\nuse crate::runtime::{self, init_vm, vm, DataArea, JavaCall, JavaThread};\nuse crate::types::{ClassRef, FrameRef, JavaThreadRef, MethodIdRef};\nuse crate::{new_br, util};\nuse std::borrow::Borrow;\n\npub struct MainThread {\n    pub class: String,\n    pub args: Vec<String>,\n    dispatch_uncaught_exception_called: bool,\n}\n\nimpl MainThread {\n    pub fn new(class: String, args: Vec<String>) -> Self {\n        Self {\n            class,\n            args,\n            dispatch_uncaught_exception_called: false,\n        }\n    }\n\n    pub fn run(&mut self) {\n        let vm = vm::VM::new(3);\n\n        //attach 'main' thread\n        vm.threads.attach_current_thread();\n\n        info!(\"init vm start\");\n        init_vm::initialize_jvm();\n        info!(\"init vm end\");\n\n        let main_class = oop::class::load_and_init(self.class.as_bytes());\n\n        let mir = {\n            let cls = main_class.get_class();\n\n            /*\n            path info should be included in \"--cp\", and avoid same class load 2\n            times, otherwise, \"<clinit>\" invoked 2 times.\n\n            For example:\n              \"MyFile.java\":\n                private static File gf = newFile();\n\n            if allowed, as follows:\n              \"cargo run -- --cp $JDK:$MY_TEST test/with_package/my.ns.HelloWorld\"\n            will cause \"<clinit>\" invoked 2 times, \"newFile()\" invoked 2 times,\n            maybe create 2 files.\n\n            should be like this:\n              \"cargo run -- --cp $JDK:$MY_TEST:test/with_package my.ns.HelloWorld\"\n            */\n            if self.class.as_bytes() != cls.name.as_slice() {\n                panic!(\"Error: Could not find or load main class {}\", self.class);\n            }\n\n            cls.get_static_method(&new_br(\"main\"), &new_br(\"([Ljava/lang/String;)V\"))\n        };\n\n        let jt = runtime::thread::current_java_thread();\n        match mir {\n            Ok(mir) => {\n                let args = self.build_main_arg();\n                let mut jc = JavaCall::new_with_args(mir, args);\n                jt.write().unwrap().is_alive = true;\n                jc.invoke(None, true);\n                jt.write().unwrap().is_alive = false;\n            }\n            _ => unreachable!(\"NotFound \\\"main\\\"\"),\n        }\n\n        if jt.read().unwrap().ex.is_some() {\n            self.uncaught_ex(main_class);\n        }\n\n        //detach main thread\n        vm.threads.detach_current_thread();\n\n        vm.threads.join_all();\n    }\n}\n\nimpl MainThread {\n    fn build_main_arg(&self) -> Vec<Oop> {\n        let args = self\n            .args\n            .iter()\n            .map(|it| util::oop::new_java_lang_string2(it))\n            .collect();\n\n        //build ArrayOopDesc\n        let ary_str_class = runtime::require_class3(None, b\"[Ljava/lang/String;\").unwrap();\n        vec![Oop::new_ref_ary2(ary_str_class, args)]\n    }\n\n    fn uncaught_ex(&mut self, main_cls: ClassRef) {\n        if self.dispatch_uncaught_exception_called {\n            self.uncaught_ex_internal();\n        } else {\n            self.dispatch_uncaught_exception_called = true;\n            self.call_dispatch_uncaught_exception(main_cls);\n        }\n    }\n\n    fn call_dispatch_uncaught_exception(&mut self, main_cls: ClassRef) {\n        let jt = runtime::thread::current_java_thread();\n        let v = {\n            let jt = jt.read().unwrap();\n            jt.java_thread_obj.clone()\n        };\n        match v {\n            Some(v) => {\n                let cls = {\n                    let rf = v.extract_ref();\n                    let inst = rf.extract_inst();\n                    inst.class.clone()\n                };\n\n                let mir = {\n                    let cls = cls.get_class();\n                    cls.get_this_class_method(\n                        &new_br(\"dispatchUncaughtException\"),\n                        &new_br(\"(Ljava/lang/Throwable;)V\"),\n                    )\n                };\n\n                match mir {\n                    Ok(mir) => {\n                        let ex = {\n                            let mut jt = jt.write().unwrap();\n                            jt.take_ex().unwrap()\n                        };\n                        let args = vec![v, ex];\n                        let mut jc = JavaCall::new_with_args(mir, args);\n                        jc.invoke(None, false);\n                    }\n                    _ => self.uncaught_ex_internal(),\n                }\n            }\n\n            None => self.uncaught_ex_internal(),\n        }\n    }\n\n    fn uncaught_ex_internal(&mut self) {\n        let jt = runtime::thread::current_java_thread();\n        let ex = {\n            let mut jt = jt.write().unwrap();\n            jt.take_ex().unwrap()\n        };\n\n        let cls = {\n            let rf = ex.extract_ref();\n            let inst = rf.extract_inst();\n            inst.class.clone()\n        };\n\n        let detail_message = {\n            let fid = {\n                let cls = cls.get_class();\n                cls.get_field_id(\n                    &new_br(\"detailMessage\"),\n                    &new_br(\"Ljava/lang/String;\"),\n                    false,\n                )\n            };\n            let v = Class::get_field_value(ex.extract_ref(), fid);\n            OopPtr::java_lang_string(v.extract_ref())\n        };\n        let name = {\n            let cls = cls.get_class();\n            cls.name.clone()\n        };\n\n        let cls_name = String::from_utf8_lossy(name.as_slice());\n        error!(\"Name={}, detailMessage={}\", cls_name, detail_message);\n    }\n}\n"
  },
  {
    "path": "crates/vm/src/runtime/thread/mod.rs",
    "content": "mod condvar;\nmod java_thread;\nmod main;\nmod mutex;\nmod thread_pool;\nmod threads;\n\npub use condvar::Condvar;\npub use java_thread::current_java_thread;\npub use java_thread::JavaThread;\npub use java_thread::THREAD;\npub use main::MainThread;\npub use mutex::raw as mutex_raw;\npub use mutex::ReentrantMutex;\npub use thread_pool::ThreadPool;\npub use threads::Threads;\n\npub use java_thread::is_meet_ex;\n"
  },
  {
    "path": "crates/vm/src/runtime/thread/mutex.rs",
    "content": "use std::cell::UnsafeCell;\nuse std::mem;\nuse std::mem::MaybeUninit;\n\n/// # Safety\npub unsafe fn raw(m: &ReentrantMutex) -> *mut libc::pthread_mutex_t {\n    m.inner.get()\n}\n\npub struct ReentrantMutex {\n    inner: UnsafeCell<libc::pthread_mutex_t>,\n}\n\nunsafe impl Send for ReentrantMutex {}\nunsafe impl Sync for ReentrantMutex {}\n\nimpl ReentrantMutex {\n    /// # Safety\n    /// todo: This function should really be documented\n    pub unsafe fn uninitialized() -> ReentrantMutex {\n        ReentrantMutex {\n            inner: mem::uninitialized(),\n        }\n    }\n\n    /// # Safety\n    /// todo: This function should really be documented\n    pub unsafe fn init(&mut self) {\n        let mut attr = MaybeUninit::<libc::pthread_mutexattr_t>::uninit();\n        let mut ptr_attr = attr.as_mut_ptr();\n        let result = libc::pthread_mutexattr_init(ptr_attr as *mut _);\n        debug_assert_eq!(result, 0);\n        let result =\n            libc::pthread_mutexattr_settype(ptr_attr as *mut _, libc::PTHREAD_MUTEX_RECURSIVE);\n        debug_assert_eq!(result, 0);\n        let result = libc::pthread_mutex_init(self.inner.get(), ptr_attr as *const _);\n        debug_assert_eq!(result, 0);\n        let result = libc::pthread_mutexattr_destroy(ptr_attr as *mut _);\n        debug_assert_eq!(result, 0);\n    }\n\n    /// # Safety\n    /// todo: This function should really be documented\n    pub unsafe fn lock(&self) {\n        let result = libc::pthread_mutex_lock(self.inner.get());\n        debug_assert_eq!(result, 0);\n    }\n\n    /// # Safety\n    /// todo: This function should really be documented\n    #[inline]\n    pub unsafe fn try_lock(&self) -> bool {\n        libc::pthread_mutex_trylock(self.inner.get()) == 0\n    }\n\n    /// # Safety\n    /// todo: This function should really be documented\n    pub unsafe fn unlock(&self) {\n        let result = libc::pthread_mutex_unlock(self.inner.get());\n        debug_assert_eq!(result, 0);\n    }\n\n    /// # Safety\n    /// todo: This function should really be documented\n    pub unsafe fn destroy(&self) {\n        let result = libc::pthread_mutex_destroy(self.inner.get());\n        debug_assert_eq!(result, 0);\n    }\n}\n"
  },
  {
    "path": "crates/vm/src/runtime/thread/thread_pool.rs",
    "content": "use crate::types::JavaThreadRef;\nuse std::sync::mpsc;\nuse std::sync::{Arc, Condvar, Mutex};\nuse std::thread;\n\npub struct ThreadPool {\n    workers: Vec<Worker>,\n    sender: mpsc::Sender<Message>,\n}\n\nenum Message {\n    NewJob(Job),\n    Terminate,\n}\n\ntrait FnBox {\n    fn call_box(self: Box<Self>);\n}\n\nimpl<F: FnOnce()> FnBox for F {\n    fn call_box(self: Box<F>) {\n        (*self)()\n    }\n}\n\ntype Job = Box<dyn FnBox + Send + 'static>;\n\nimpl ThreadPool {\n    /// Create a new ThreadPool.\n    ///\n    /// The size is the number of threads in the pool.\n    ///\n    /// # Panics\n    ///\n    /// The `new` function will panic if the size is zero.\n    pub fn new(size: usize) -> ThreadPool {\n        assert!(size > 0);\n\n        let (sender, receiver) = mpsc::channel();\n\n        let receiver = Arc::new(Mutex::new(receiver));\n\n        let mut workers = Vec::with_capacity(size);\n\n        for id in 0..size {\n            workers.push(Worker::new(id, Arc::clone(&receiver)));\n        }\n\n        ThreadPool { workers, sender }\n    }\n\n    pub fn execute<F>(&self, f: F)\n    where\n        F: FnOnce() + Send + 'static,\n    {\n        let job = Box::new(f);\n        self.sender.send(Message::NewJob(job)).unwrap();\n    }\n}\n\nimpl Drop for ThreadPool {\n    fn drop(&mut self) {\n        info!(\"Sending terminate message to all workers.\");\n\n        for _ in &mut self.workers {\n            self.sender.send(Message::Terminate).unwrap();\n        }\n\n        info!(\"Shutting down all workers.\");\n\n        for worker in &mut self.workers {\n            info!(\"Shutting down worker {}\", worker.id);\n\n            if let Some(thread) = worker.thread.take() {\n                thread.join().unwrap();\n            }\n        }\n    }\n}\n\nstruct Worker {\n    id: usize,\n    thread: Option<thread::JoinHandle<()>>,\n}\n\nimpl Worker {\n    fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Message>>>) -> Worker {\n        let thread = thread::spawn(move || loop {\n            let message = receiver.lock().unwrap().recv().unwrap();\n\n            match message {\n                Message::NewJob(job) => {\n                    warn!(\"Worker-{} got a job, executing\", id);\n                    job.call_box();\n                    warn!(\"Worker-{}, fin\", id);\n                }\n                Message::Terminate => {\n                    warn!(\"Worker {} was told to terminate.\", id);\n                    break;\n                }\n            }\n        });\n\n        Worker {\n            id,\n            thread: Some(thread),\n        }\n    }\n}\n"
  },
  {
    "path": "crates/vm/src/runtime/thread/threads.rs",
    "content": "use crate::runtime;\nuse crate::runtime::thread::ThreadPool;\nuse crate::types::JavaThreadRef;\nuse std::borrow::Borrow;\nuse std::sync::atomic::{AtomicBool, AtomicI64, Ordering};\nuse std::sync::{Arc, Condvar, Mutex};\n\npub struct Threads {\n    pool: Mutex<ThreadPool>,\n    threads: Mutex<Vec<JavaThreadRef>>,\n    cond_join: Condvar,\n    next_id: AtomicI64,\n}\n\nimpl Threads {\n    pub fn new(thread_pool_count: usize) -> Threads {\n        Threads {\n            pool: Mutex::new(ThreadPool::new(thread_pool_count)),\n            threads: Mutex::new(Vec::new()),\n            cond_join: Condvar::new(),\n            next_id: AtomicI64::new(1),\n        }\n    }\n}\n\nimpl Threads {\n    pub fn next_id(&self) -> i64 {\n        self.next_id.fetch_add(1, Ordering::SeqCst)\n    }\n\n    pub fn attach_current_thread(&self) {\n        runtime::thread::THREAD.with(|thread| {\n            let mut threads = self.threads.lock().unwrap();\n            threads.push(thread.borrow().clone());\n        });\n    }\n\n    pub fn attach_java_thread(&self, thread: JavaThreadRef) {\n        let mut threads = self.threads.lock().unwrap();\n        threads.push(thread);\n    }\n\n    pub fn detach_current_thread(&self) {\n        runtime::thread::THREAD.with(|thread| {\n            let mut threads = self.threads.lock().unwrap();\n            threads.retain(|elem| !Arc::ptr_eq(elem, &*thread.borrow()));\n            self.cond_join.notify_all();\n        });\n    }\n\n    pub fn find_java_thread(&self, eetop: i64) -> Option<JavaThreadRef> {\n        let mut threads = self.threads.lock().unwrap();\n        threads\n            .iter()\n            .find(|t| t.read().unwrap().eetop == eetop)\n            .cloned()\n    }\n\n    pub fn join_all(&self) {\n        let mut threads = self.threads.lock().unwrap();\n\n        while threads.len() > 0 {\n            threads = self.cond_join.wait(threads).unwrap();\n        }\n    }\n\n    pub fn spawn_java_thread<F: FnOnce() + Send + 'static>(&self, f: F) {\n        let pool = self.pool.lock().unwrap();\n        pool.execute(f);\n    }\n}\n"
  },
  {
    "path": "crates/vm/src/runtime/vm.rs",
    "content": "use crate::runtime::thread::Threads;\nuse std::ptr;\n\nstatic mut VM_GLOBAL: *const u8 = ptr::null();\n\npub fn get_vm() -> &'static VM {\n    unsafe { &*(VM_GLOBAL as *const VM) }\n}\n\npub fn set_vm(vm: &VM) {\n    let ptr = vm as *const _ as *const u8;\n\n    unsafe {\n        VM_GLOBAL = ptr;\n    }\n}\n\npub struct VM {\n    pub threads: Threads,\n}\n\nimpl VM {\n    pub fn new(thread_pool_count: usize) -> Box<VM> {\n        let vm = Box::new(VM {\n            threads: Threads::new(thread_pool_count),\n        });\n\n        set_vm(&vm);\n\n        vm\n    }\n}\n"
  },
  {
    "path": "crates/vm/src/types.rs",
    "content": "use crate::oop::class::ClassPtr;\nuse crate::oop::field::FieldId;\nuse crate::runtime::method::MethodId;\nuse crate::runtime::Frame;\nuse crate::runtime::JavaThread;\nuse classfile::ClassFile;\nuse std::sync::Arc;\n\npub type FieldIdRef = Arc<FieldId>;\npub type MethodIdRef = Arc<MethodId>;\npub type ClassRef = Arc<ClassPtr>;\n\ndef_ref!(ClassFileRef, ClassFile);\ndef_sync_ref!(FrameRef, Frame);\ndef_sync_ref!(JavaThreadRef, JavaThread);\n\n// Runtime string allocation\ndef_ptr!(ByteAry, Vec<u8>);\ndef_ptr!(BoolAry, Vec<u8>);\ndef_ptr!(CharAry, Vec<u16>);\ndef_ptr!(ShortAry, Vec<i16>);\ndef_ptr!(IntAry, Vec<i32>);\ndef_ptr!(LongAry, Vec<i64>);\ndef_ptr!(FloatAry, Vec<f32>);\ndef_ptr!(DoubleAry, Vec<f64>);\n"
  },
  {
    "path": "crates/vm/src/util/attributes.rs",
    "content": "use classfile::{AttributeType, BytesRef};\n\npub fn assemble_annotation(attrs: &[AttributeType]) -> Option<Vec<u8>> {\n    let mut vis = None;\n    let mut in_vis = None;\n\n    for it in attrs.iter() {\n        match it {\n            AttributeType::RuntimeVisibleAnnotations { raw, .. } => {\n                vis = Some(raw.clone());\n            }\n            AttributeType::RuntimeInvisibleAnnotations { raw, .. } => {\n                in_vis = Some(raw.clone());\n            }\n            _ => (),\n        }\n    }\n\n    do_assemble(vis, in_vis)\n}\n\npub fn assemble_param_annotation(attrs: &[AttributeType]) -> Option<Vec<u8>> {\n    let mut vis = None;\n    let mut in_vis = None;\n\n    for it in attrs.iter() {\n        match it {\n            AttributeType::RuntimeVisibleParameterAnnotations { raw, .. } => {\n                vis = Some(raw.clone());\n            }\n            AttributeType::RuntimeInvisibleParameterAnnotations { raw, .. } => {\n                in_vis = Some(raw.clone());\n            }\n            _ => (),\n        }\n    }\n\n    do_assemble(vis, in_vis)\n}\n\npub fn assemble_type_annotation(attrs: &[AttributeType]) -> Option<Vec<u8>> {\n    let mut vis = None;\n    let mut in_vis = None;\n\n    for it in attrs.iter() {\n        match it {\n            AttributeType::RuntimeVisibleTypeAnnotations { raw, .. } => {\n                vis = Some(raw.clone());\n            }\n            AttributeType::RuntimeInvisibleTypeAnnotations { raw, .. } => {\n                in_vis = Some(raw.clone());\n            }\n            _ => (),\n        }\n    }\n\n    do_assemble(vis, in_vis)\n}\n\npub fn assemble_annotation_default(attrs: &[AttributeType]) -> Option<Vec<u8>> {\n    let mut vis = None;\n\n    for it in attrs.iter() {\n        if let AttributeType::AnnotationDefault { raw, .. } = it {\n            vis = Some(raw.clone());\n        }\n    }\n\n    do_assemble(vis, None)\n}\n\npub fn get_signature(attrs: &[AttributeType]) -> u16 {\n    for it in attrs.iter() {\n        if let AttributeType::Signature { signature_index } = it {\n            return *signature_index;\n        }\n    }\n\n    0\n}\n\nfn do_assemble(vis: Option<BytesRef>, in_vis: Option<BytesRef>) -> Option<Vec<u8>> {\n    let mut raw = None;\n\n    if let Some(v) = vis {\n        raw = Some(Vec::from(v.as_slice()));\n    }\n\n    if let Some(v) = in_vis {\n        if let Some(raw) = raw.as_mut() {\n            raw.extend_from_slice(v.as_slice());\n        }\n    }\n\n    raw\n}\n"
  },
  {
    "path": "crates/vm/src/util/consts.rs",
    "content": "use crate::new_br;\nuse classfile::BytesRef;\n\nlazy_static! {\n    pub static ref S_INIT: BytesRef = new_br(\"<init>\");\n    pub static ref S_CLINIT: BytesRef = new_br(\"<clinit>\");\n    pub static ref S_CLINIT_SIG: BytesRef = new_br(\"()V\");\n    pub static ref S_RUN_SIG: BytesRef = new_br(\"()Ljava/lang/Object;\");\n    pub static ref S_NEW_STRING_SIG: BytesRef = new_br(\"([C)V\");\n    pub static ref S_CLAZZ: BytesRef = new_br(\"clazz\");\n    pub static ref S_FD: BytesRef = new_br(\"fd\");\n    pub static ref S_I: BytesRef = new_br(\"I\");\n    pub static ref S_SLOT: BytesRef = new_br(\"slot\");\n    pub static ref S_MODIFIERS: BytesRef = new_br(\"modifiers\");\n    pub static ref S_NAME: BytesRef = new_br(\"name\");\n    pub static ref S_SIGNATURE: BytesRef = new_br(\"signature\");\n    pub static ref S_CONSTANT_POOL_OOP: BytesRef = new_br(\"constantPoolOop\");\n    pub static ref S_RUN: BytesRef = new_br(\"run\");\n    pub static ref S_ERR: BytesRef = new_br(\"err\");\n    pub static ref S_OUT: BytesRef = new_br(\"out\");\n    pub static ref S_IN: BytesRef = new_br(\"in\");\n    pub static ref S_JAVA_LANG_CLASS: BytesRef = new_br(\"Ljava/lang/Class;\");\n    pub static ref S_JAVA_LANG_OBJECT: BytesRef = new_br(\"Ljava/lang/Object;\");\n    pub static ref S_JAVA_LANG_STRING: BytesRef = new_br(\"Ljava/lang/String;\");\n    pub static ref S_JAVA_IO_FD: BytesRef = new_br(\"Ljava/io/FileDescriptor;\");\n    pub static ref S_JAVA_IO_PRINT_STREAM: BytesRef = new_br(\"Ljava/io/PrintStream;\");\n    pub static ref S_JAVA_IO_INPUT_STREAM: BytesRef = new_br(\"Ljava/io/InputStream;\");\n}\n"
  },
  {
    "path": "crates/vm/src/util/debug.rs",
    "content": "#![allow(unused)]\n\nuse crate::runtime::thread::JavaThread;\nuse std::fmt::Write;\nuse std::sync::atomic::Ordering;\n\npub fn print_stack_trace(jt: &JavaThread) {\n    let mut w = String::new();\n\n    let _ = writeln!(&mut w);\n    for (count, it) in jt.frames.iter().enumerate().rev() {\n        let frame = it.read().unwrap();\n        let cls = frame.mir.method.class.get_class();\n        let method_id = frame.mir.method.name.clone();\n        let line_num = {\n            let pc = frame.pc.load(Ordering::Relaxed);\n            frame.mir.method.get_line_num(pc as u16)\n        };\n\n        let _ = writeln!(\n            &mut w,\n            \"{}{}:{}(:{})\",\n            \" \".repeat(jt.frames.len() - count),\n            String::from_utf8_lossy(cls.name.as_slice()),\n            String::from_utf8_lossy(method_id.as_slice()),\n            line_num\n        );\n    }\n\n    error!(\"{}\", w);\n}\n"
  },
  {
    "path": "crates/vm/src/util/macros.rs",
    "content": "#[macro_export]\nmacro_rules! def_sync_ref {\n    ($name:ident, $t:ty) => {\n        pub type $name = std::sync::Arc<std::sync::RwLock<Box<$t>>>;\n    };\n}\n\n/*\nmacro_rules! def_already_boxed_ref {\n    ($name:ident, $t:ty) => {\n        pub type $name = std::sync::Arc<$t>;\n    };\n}\n*/\n\n#[macro_export]\nmacro_rules! def_ref {\n    ($name:ident, $t:ty) => {\n        pub type $name = std::sync::Arc<Box<$t>>;\n    };\n}\n\n#[macro_export]\nmacro_rules! def_ptr {\n    ($name:ident, $t:ty) => {\n        pub type $name = Box<$t>;\n    };\n}\n\n#[macro_export]\nmacro_rules! new_sync_ref {\n    ($name:ident) => {\n        std::sync::Arc::new(std::sync::RwLock::new(Box::new($name)));\n    };\n}\n\n#[macro_export]\nmacro_rules! new_ref {\n    ($name:ident) => {\n        std::sync::Arc::new(Box::new($name));\n    };\n}\n"
  },
  {
    "path": "crates/vm/src/util/mod.rs",
    "content": "#[macro_use]\npub mod macros;\n\npub mod attributes;\nmod consts;\npub mod debug;\npub mod oop;\nmod sys;\n\npub use self::consts::*;\npub use self::sys::*;\n\nuse classfile::BytesRef;\nuse std::sync::Arc;\n\npub fn new_field_id(cls: &[u8], name: &[u8], desc: &[u8]) -> BytesRef {\n    Arc::new(vec![cls, name, desc].join(PATH_SEP.as_bytes()))\n}\n"
  },
  {
    "path": "crates/vm/src/util/oop.rs",
    "content": "use crate::oop::Oop;\nuse crate::runtime::{self, require_class3};\nuse crate::util;\n\nstatic mut JAVA_LANG_STRING_VALUE_OFFSET: usize = 0;\nstatic mut JAVA_LANG_INTEGER_VALUE_OFFSET: usize = 0;\n\npub fn set_java_lang_string_value_offset(offset: usize) {\n    unsafe {\n        JAVA_LANG_STRING_VALUE_OFFSET = offset;\n    }\n}\n\npub fn set_java_lang_integer_value_offset(offset: usize) {\n    unsafe {\n        JAVA_LANG_INTEGER_VALUE_OFFSET = offset;\n    }\n}\n\npub fn get_java_lang_string_value_offset() -> usize {\n    unsafe { JAVA_LANG_STRING_VALUE_OFFSET }\n}\n\npub fn get_java_lang_integer_value_offset() -> usize {\n    unsafe { JAVA_LANG_INTEGER_VALUE_OFFSET }\n}\n\npub fn new_java_lang_string2(v: &str) -> Oop {\n    //build \"char value[]\"\n    let chars: Vec<u16> = v.as_bytes().iter().map(|v| *v as u16).collect();\n    let ary = Oop::char_ary_from1(chars.as_slice());\n\n    //new String(char value[])\n    let string_cls = require_class3(None, b\"java/lang/String\").unwrap();\n    let string_oop = Oop::new_inst(string_cls.clone());\n    let args = vec![string_oop.clone(), ary];\n    runtime::invoke::invoke_ctor(string_cls, util::S_NEW_STRING_SIG.clone(), args);\n\n    string_oop\n}\n\npub fn new_java_lang_string3(bs: &[u8]) -> Oop {\n    let buffer = classfile::constant_pool::construct_string_raw(bs);\n\n    //build \"char value[]\"\n    let ary = Oop::char_ary_from1(buffer.as_slice());\n\n    //new String(char value[])\n    let string_cls = require_class3(None, b\"java/lang/String\").unwrap();\n    let string_oop = Oop::new_inst(string_cls.clone());\n    let args = vec![string_oop.clone(), ary];\n    runtime::invoke::invoke_ctor(string_cls, util::S_NEW_STRING_SIG.clone(), args);\n\n    string_oop\n}\n"
  },
  {
    "path": "crates/vm/src/util/sys.rs",
    "content": "#![allow(unused)]\n\npub const FILE_SEP: &str = platform::FILE_SEP;\npub const PATH_SEP: &str = platform::PATH_SEP;\npub const LINE_SEP: &str = \"\\n\";\n\n#[cfg(unix)]\nmod platform {\n    pub const FILE_SEP: &str = \"/\";\n    pub const PATH_SEP: &str = \":\";\n}\n\n#[cfg(windows)]\nmod platform {\n    pub const FILE_SEP: &str = \"\\\\\";\n    pub const PATH_SEP: &str = \";\";\n}\n"
  },
  {
    "path": "jvm/Cargo.toml",
    "content": "[package]\nname = \"jvm\"\nversion = \"0.2.0\"\nauthors = [\"douchuan <1843657913@qq.com>\"]\nedition = \"2018\"\n\n[dependencies]\nclap = \"3.0.0-beta.1\"\nclass-parser = { path = \"../crates/class-parser\", version = \"0.1.0\" }\nenv_logger = \"0.8.2\"\nvm = { path = \"../crates/vm\", version = \"0.1.0\" }\n\n[dev-dependencies]\nclassfile = { path = \"../crates/classfile\", version = \"0.1.0\" }\nlibc = \"0.2.71\"\n"
  },
  {
    "path": "jvm/README.md",
    "content": "## jvm \n\nThe executable program of jvm.\n\n## Usage\n\nModify the run.sh script according to your environment.\n\nIf you installed JDK, but can not find jre path, try:\n\n```shell\njava -XshowSettings:properties\n```\n"
  },
  {
    "path": "jvm/r.sh",
    "content": "#########################################\n#modify to according to your env\n#\n#If you installed JDK, but can not find jre path, try:\n#java -XshowSettings:properties\n#\n#On Linux, maybe\n#JAVA_HOME=\"/usr/lib/jvm/java-1.8.0-openjdk-amd64/jre\"\n#########################################\nJAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre\n########################################\n\nMY_SAMPLE=sample\n\n##############################################\nfunction join_by { local IFS=\"$1\"; shift; echo \"$*\"; }\n##############################################\n\n#FIXME: win should be ';'\nSEP=':'\n\njars=$JAVA_HOME/lib/*.jar\nJDK=$(join_by $SEP ${jars[@]})\n\nexport JAVA_HOME\ncargo run -- --cp $JDK:$MY_SAMPLE HelloWorld\n"
  },
  {
    "path": "jvm/sample/HelloWorld.java",
    "content": "class HelloWorld\n{\n    public static void main(String[] args)\n    {\n    \tSystem.out.println(\"Hello, World.\");\n    }\n} \n"
  },
  {
    "path": "jvm/src/main.rs",
    "content": "extern crate clap;\nextern crate env_logger;\n\nmod options;\n\nuse vm;\nuse vm::runtime::{self, thread::MainThread};\nuse vm::util;\n\nfn main() {\n    env_logger::init();\n    vm::init_vm();\n\n    let opt = options::parse();\n\n    if let Some(cp) = &opt.cp {\n        runtime::add_class_paths(cp);\n    }\n\n    if let Some(classpath) = &opt.classpath {\n        runtime::add_class_path(classpath);\n    }\n\n    let class = opt.class;\n    let args = opt.args;\n    // println!(\"main class: {}, args: {:?}\", class, args);\n    let mut thread = MainThread::new(class.replace(\".\", util::FILE_SEP), args);\n    thread.run();\n}\n"
  },
  {
    "path": "jvm/src/options.rs",
    "content": "use clap::Clap;\n\n#[derive(Clap, Debug)]\n#[clap(version)]\npub struct Opt {\n    /// class search path of directories and zip/jar files\n    #[clap(long)]\n    pub cp: Option<String>,\n\n    /// class search path of directories and zip/jar files\n    #[clap(long)]\n    pub classpath: Option<String>,\n\n    #[clap(required = true)]\n    pub class: String,\n\n    pub args: Vec<String>,\n}\n\npub fn parse() -> Opt {\n    Opt::parse()\n}\n"
  },
  {
    "path": "jvm/t.sh",
    "content": "\n#########################################\n###modify to according to your env\nJAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre\nJDK_SRC=/Users/douchuan/work/codes/vm/openjdk8\n########################################\n\nJDK=$JAVA_HOME/lib/resources.jar:$JAVA_HOME/lib/rt.jar:$JAVA_HOME/lib/jsse.jar:$JAVA_HOME/lib/jce.jar:$JAVA_HOME/lib/charsets.jar:$JAVA_HOME/lib/jfr.jar\nJDK_T_LANG=$JDK_SRC/jdk/test/java/lang\nJDK_T_SM=$JDK_SRC/jdk/test/sun/misc\nMY_TEST=.:./test\n\nexport JAVA_HOME\n\n#export RUST_LOG=warn\n#export RUST_LOG=info\n#export RUST_LOG=trace\nexport RUST_BACKTRACE=full\n\n\n### My Test\n#cargo run -- --cp $JDK:$MY_TEST Add\n#cargo run -- --cp $JDK:$MY_TEST MyHelloWorld 123 456 789\n#cargo run -- --cp $JDK:$MY_TEST HelloWorldUnicode\n#cargo run -- --cp $JDK:$MY_TEST Ex\n#cargo run -- --cp $JDK:$MY_TEST MyFile\n#cargo run -- --cp $JDK:$MY_TEST MyInteger\n#cargo run -- --cp $JDK:$MY_TEST MyArrayCopy\n#cargo run -- --cp $JDK:$MY_TEST ThreadTest\n#cargo run -- --cp $JDK:$MY_TEST ThreadTest2\n### no 'join' in main thread\n#cargo run -- --cp $JDK:$MY_TEST ThreadTest3\n\n### fix Overflow\n#cargo run -- --cp $JDK:$MY_TEST SubOverflow\n\n### fix Enum CloneNotSupportedException\n#cargo run -- --cp $JDK:$MY_TEST EnumDemo\n\n### fix System.out.printf not work, resolve_again for acc_flags == 0\n#cargo run -- --cp $JDK:$MY_TEST Printf\n\n### fix ThreadLocal not work, resolve_again for protected\n#cargo run -- --cp $JDK:$MY_TEST ThreadLocalTest\n\n### load with custom package\n## should panic\n#cargo run -- --cp $JDK:$MY_TEST test/with_package/my.ns.HelloWorld\n## ok\n#cargo run -- --cp $JDK:$MY_TEST:test/with_package my.ns.HelloWorld\n\n\n###regex\n## System.out.printf not work\n##\n## 原因1: invoke_virtual定位method错误\n##  因为java.util.regex.Pattern$Node.match方法的acc_flags==0,\n##导致没有resolve_again，acc_flags为0的含义是什么?\n##  java.util.regex.Pattern$Node.match (错误的找到这个method)\n##  java.util.regex.Pattern$Start.match (应该用这个)\n##\n## 原因2：\n##   java.util.Formatter$FormatSpecifier.conversion(String)\n## 调用Character.toLowerCase(c)转换错误\n##   码表在java/lang/CharacterDataLatin1中, ldc CONSTANT_String_info 加载\n##\n## Modified UTF-8 strings 编码定义:\n## JVM Spec, 4.4.7 The CONSTANT_Utf8_info Structure 定义\n#cargo run -- --cp $JDK:$MY_TEST:./test/regex Printf\n\n###\n##Float.toString(1.0f) crash\n##ThreadLocal.initialValue not called, so NPE happend\n#cargo run -- --cp $JDK:$MY_TEST:./test/float ToString\n#cargo run -- --cp $JDK:$MY_TEST:./test/char MyCheckScript\n#cargo run -- --cp $JDK:$MY_TEST:./test/annotation AnnotationTest\n\n###############################\n### jdk test\n###############################\n#cargo run -- --cp $JDK:$JDK_T_LANG Compare\n#cargo run -- --cp $JDK:$JDK_T_LANG HashCode\n#cargo run -- --cp $JDK:$JDK_T_LANG ToString\n#cargo run -- --cp $JDK:$JDK_T_LANG:$JDK_T_LANG/Appendable Basic\n#cargo run -- --cp $JDK:$JDK_T_LANG:$JDK_T_LANG/AssertionError Cause\n#cargo run -- --cp $JDK:$JDK_T_LANG:$JDK_T_LANG/Boolean Factory\n#cargo run -- --cp $JDK:$JDK_T_LANG:$JDK_T_LANG/Boolean GetBoolean\n#cargo run -- --cp $JDK:$JDK_T_LANG:$JDK_T_LANG/Boolean MakeBooleanComparable\n#cargo run -- --cp $JDK:$JDK_T_LANG:$JDK_T_LANG/Boolean ParseBoolean\n#cargo run -- --cp $JDK:$JDK_T_LANG:$JDK_T_LANG/Byte Decode\n#cargo run -- --cp $JDK:$JDK_T_LANG:$JDK_T_LANG/Class ArrayMethods\n#cargo run -- --cp $JDK:$JDK_T_LANG:$JDK_T_LANG/Class GenericStringTest\n#cargo run -- --cp $JDK:$JDK_T_LANG:$JDK_T_LANG/Class IsEnum\n##TODO: GC needed\n#cargo run -- --cp $JDK:$JDK_T_LANG:$JDK_T_LANG/Class TypeCheckMicroBenchmark\n#cargo run -- --cp $JDK:$JDK_T_LANG:$JDK_T_LANG/Class Cast\n#cargo run -- --cp $JDK:$JDK_T_LANG:$JDK_T_LANG/Class IsAnnotationType\n#cargo run -- --cp $JDK:$JDK_T_LANG:$JDK_T_LANG/Class IsSynthetic\n#cargo run -- --cp $JDK:$JDK_T_LANG:$JDK_T_LANG/Class/asSubclass BasicUnit\n#cargo run -- --cp $JDK:$JDK_T_LANG:$JDK_T_LANG/Class/forName InitArg\n#cargo run -- --cp $JDK:$JDK_T_LANG:$JDK_T_LANG/Class/forName InvalidNameWithSlash\n#cargo run -- --cp $JDK:$JDK_T_LANG:$JDK_T_LANG/Class/forName NonJavaNames\n#cargo run -- --cp $JDK:$JDK_T_LANG:$JDK_T_LANG/Class/forName Z\n#cargo run -- --cp $JDK:$JDK_T_LANG:$JDK_T_LANG/Class/getClasses Sanity\n\n#cargo run -- --cp $JDK:$JDK_T_LANG:$JDK_T_LANG/Math AbsPositiveZero\n\n##jdk/test/sun/misc\n#TODO: CopyMemory getUnsafe return null\n#cargo run -- --cp $JDK:$JDK_T_LANG:$JDK_T_SM MyCopyMemory\n#cargo run -- --cp $JDK:$JDK_T_LANG:$JDK_T_SM Safe\n\n##TODO: depend on testng\n##IntegralPrimitiveToString.java, PrimitiveSumMinMaxTest.java\n##CharSequence/DefaultTest.java\n\n##TODO: optimize\n################################\n### oracle java\n#sum_t_list_add = 16\n#sum_t_map_get = 1\n#sum_t_map_put = 1\n#sum_t_parse_int = 3\n#sum_t_println = 26\n#sum_t_int2integer = 13\n#################################\n### mine release mode\n#sum_t_list_add = 1507\n#sum_t_map_get = 27\n#sum_t_map_put = 3\n#sum_t_parse_int = 159\n#sum_t_println = 768\n#sum_t_int2integer = 1255\nexport TEST_SRC=$JDK_SRC/jdk/test/java/lang/Character\ncargo run --release -- --cp $JDK:$JDK_T_LANG:$JDK_T_LANG/Character MyCheckProp\n#cargo run -- --cp $JDK:$JDK_T_LANG:$JDK_T_LANG/Character MyCheckProp\n#cargo run --release -- --cp $JDK:$JDK_T_LANG:$JDK_T_LANG/Character MyCheckProp1\n#cargo run --release -- --cp $JDK:$JDK_T_LANG:$JDK_T_LANG/Character CheckProp\n#cargo run --release -- --cp $JDK:$JDK_T_LANG:$JDK_T_LANG/Character CheckScript\n\n#cargo run -- --cp $JDK:$JDK_T_LANG:$JDK_T_LANG/reflect/Constructor TestParameterAnnotations\n\n##TODO: NonJavaNames just ignored currently\n##NonJavaNames\n\n##TODO: impl getDeclaredClasses0\n#cargo run -- --cp $JDK:$JDK_T_LANG:$JDK_T_LANG/Class/getClasses Sanity\n\n\n############################################\n###perf (linux)\n############################################\n#export TEST_SRC=$JDK_SRC/jdk/test/java/lang/Character\n#perf record --call-graph dwarf -- cargo run --release -- --cp $JDK:$JDK_T_LANG:$JDK_T_LANG/Character MyCheckProp\n#perf report\n"
  },
  {
    "path": "libjvm/Cargo.toml",
    "content": "[package]\nname = \"libjvm\"\nversion = \"0.1.0\"\nauthors = [\"Лач <iam@lach.pw>\"]\nedition = \"2018\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\njni-sys = \"0.3.0\"\nlibc = \"0.2.68\"\nlazy_static = \"1.4.0\"\nvm = { path = \"../crates/vm\", version = \"0.1.0\" }\n\n[lib]\nname = \"jvm\"\ncrate-type = [\"cdylib\"]\n\n[profile.dev]\npanic = \"abort\"\n\n[profile.release]\npanic = \"abort\"\n"
  },
  {
    "path": "libjvm/README.md",
    "content": "## jvm\n\nDrop-in implementation of libjvm.so/jvm.dll\n\n## Usage\n\nCompile and copy to `openjdk root/lib/amd64/server/libjvm.so`\n"
  },
  {
    "path": "libjvm/src/invocation.rs",
    "content": "#![allow(non_snake_case)]\n#![allow(unused_imports)]\n\n//https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/invocation.html\n\nuse jni_sys::{jboolean, jint, jsize, JNIInvokeInterface_, JNINativeInterface_, JavaVM};\nuse lazy_static::lazy_static;\nuse libc::c_void;\nuse std::cell::RefCell;\nuse std::sync::Mutex;\nuse vm::runtime::thread::MainThread;\n\nuse crate::native;\n\n#[no_mangle]\nextern \"C\" fn JNI_GetDefaultJavaVMInitArgs(args: *mut c_void) -> jint {\n\t0\n}\n\n#[derive(Clone)]\nstruct VMHolder {\n\tjvm: Box<JNIInvokeInterface_>,\n}\nunsafe impl Send for VMHolder {}\nunsafe impl Sync for VMHolder {}\n\nimpl VMHolder {\n\tfn inner(&self) -> JavaVM {\n\t\tself.jvm.as_ref() as *const _\n\t}\n}\n\n// TODO: Hotspot doesn't supports creation of multiple JVMs per process, should we?\nlazy_static! {\n\tstatic ref JVM: Mutex<Option<VMHolder>> = Mutex::new(None);\n}\n\nunsafe extern \"system\" fn DestroyJavaVM(_vm: *mut JavaVM) -> jint {\n\ttodo!();\n}\nunsafe extern \"system\" fn AttachCurrentThread(\n\t_vm: *mut JavaVM,\n\t_penv: *mut *mut c_void,\n\t_args: *mut c_void,\n) -> jint {\n\ttodo!();\n}\nunsafe extern \"system\" fn DetachCurrentThread(_vm: *mut JavaVM) -> jint {\n\ttodo!();\n}\nunsafe extern \"system\" fn GetEnv(\n\t_vm: *mut JavaVM,\n\tpenv: *mut *mut core::ffi::c_void,\n\t_version: jint,\n) -> jint {\n\tuse std::ptr::null_mut;\n\t*penv = Box::into_raw(Box::new(JNINativeInterface_ {\n\t\treserved0: null_mut(),\n\t\treserved1: null_mut(),\n\t\treserved2: null_mut(),\n\t\treserved3: null_mut(),\n\t\tGetVersion: Some(native::GetVersion),\n\t\tDefineClass: Some(native::DefineClass),\n\t\tFindClass: Some(native::FindClass),\n\t\tFromReflectedMethod: Some(native::FromReflectedMethod),\n\t\tFromReflectedField: Some(native::FromReflectedField),\n\t\tToReflectedMethod: Some(native::ToReflectedMethod),\n\t\tGetSuperclass: Some(native::GetSuperclass),\n\t\tIsAssignableFrom: Some(native::IsAssignableFrom),\n\t\tToReflectedField: Some(native::ToReflectedField),\n\t\tThrow: Some(native::Throw),\n\t\tThrowNew: Some(native::ThrowNew),\n\t\tExceptionOccurred: Some(native::ExceptionOccurred),\n\t\tExceptionDescribe: Some(native::ExceptionDescribe),\n\t\tExceptionClear: Some(native::ExceptionClear),\n\t\tFatalError: Some(native::FatalError),\n\t\tPushLocalFrame: Some(native::PushLocalFrame),\n\t\tPopLocalFrame: Some(native::PopLocalFrame),\n\t\tNewGlobalRef: Some(native::NewGlobalRef),\n\t\tDeleteGlobalRef: Some(native::DeleteGlobalRef),\n\t\tDeleteLocalRef: Some(native::DeleteLocalRef),\n\t\tIsSameObject: Some(native::IsSameObject),\n\t\tNewLocalRef: Some(native::NewLocalRef),\n\t\tEnsureLocalCapacity: Some(native::EnsureLocalCapacity),\n\t\tAllocObject: Some(native::AllocObject),\n\t\tNewObject: Some(native::NewObject),\n\t\tNewObjectV: Some(native::NewObjectV),\n\t\tNewObjectA: Some(native::NewObjectA),\n\t\tGetObjectClass: Some(native::GetObjectClass),\n\t\tIsInstanceOf: Some(native::IsInstanceOf),\n\t\tGetMethodID: Some(native::GetMethodID),\n\t\tCallObjectMethod: Some(native::CallObjectMethod),\n\t\tCallObjectMethodV: Some(native::CallObjectMethodV),\n\t\tCallObjectMethodA: Some(native::CallObjectMethodA),\n\t\tCallBooleanMethod: Some(native::CallBooleanMethod),\n\t\tCallBooleanMethodV: Some(native::CallBooleanMethodV),\n\t\tCallBooleanMethodA: Some(native::CallBooleanMethodA),\n\t\tCallByteMethod: Some(native::CallByteMethod),\n\t\tCallByteMethodV: Some(native::CallByteMethodV),\n\t\tCallByteMethodA: Some(native::CallByteMethodA),\n\t\tCallCharMethod: Some(native::CallCharMethod),\n\t\tCallCharMethodV: Some(native::CallCharMethodV),\n\t\tCallCharMethodA: Some(native::CallCharMethodA),\n\t\tCallShortMethod: Some(native::CallShortMethod),\n\t\tCallShortMethodV: Some(native::CallShortMethodV),\n\t\tCallShortMethodA: Some(native::CallShortMethodA),\n\t\tCallIntMethod: Some(native::CallIntMethod),\n\t\tCallIntMethodV: Some(native::CallIntMethodV),\n\t\tCallIntMethodA: Some(native::CallIntMethodA),\n\t\tCallLongMethod: Some(native::CallLongMethod),\n\t\tCallLongMethodV: Some(native::CallLongMethodV),\n\t\tCallLongMethodA: Some(native::CallLongMethodA),\n\t\tCallFloatMethod: Some(native::CallFloatMethod),\n\t\tCallFloatMethodV: Some(native::CallFloatMethodV),\n\t\tCallFloatMethodA: Some(native::CallFloatMethodA),\n\t\tCallDoubleMethod: Some(native::CallDoubleMethod),\n\t\tCallDoubleMethodV: Some(native::CallDoubleMethodV),\n\t\tCallDoubleMethodA: Some(native::CallDoubleMethodA),\n\t\tCallVoidMethod: Some(native::CallVoidMethod),\n\t\tCallVoidMethodV: Some(native::CallVoidMethodV),\n\t\tCallVoidMethodA: Some(native::CallVoidMethodA),\n\t\tCallNonvirtualObjectMethod: Some(native::CallNonvirtualObjectMethod),\n\t\tCallNonvirtualObjectMethodV: Some(native::CallNonvirtualObjectMethodV),\n\t\tCallNonvirtualObjectMethodA: Some(native::CallNonvirtualObjectMethodA),\n\t\tCallNonvirtualBooleanMethod: Some(native::CallNonvirtualBooleanMethod),\n\t\tCallNonvirtualBooleanMethodV: Some(native::CallNonvirtualBooleanMethodV),\n\t\tCallNonvirtualBooleanMethodA: Some(native::CallNonvirtualBooleanMethodA),\n\t\tCallNonvirtualByteMethod: Some(native::CallNonvirtualByteMethod),\n\t\tCallNonvirtualByteMethodV: Some(native::CallNonvirtualByteMethodV),\n\t\tCallNonvirtualByteMethodA: Some(native::CallNonvirtualByteMethodA),\n\t\tCallNonvirtualCharMethod: Some(native::CallNonvirtualCharMethod),\n\t\tCallNonvirtualCharMethodV: Some(native::CallNonvirtualCharMethodV),\n\t\tCallNonvirtualCharMethodA: Some(native::CallNonvirtualCharMethodA),\n\t\tCallNonvirtualShortMethod: Some(native::CallNonvirtualShortMethod),\n\t\tCallNonvirtualShortMethodV: Some(native::CallNonvirtualShortMethodV),\n\t\tCallNonvirtualShortMethodA: Some(native::CallNonvirtualShortMethodA),\n\t\tCallNonvirtualIntMethod: Some(native::CallNonvirtualIntMethod),\n\t\tCallNonvirtualIntMethodV: Some(native::CallNonvirtualIntMethodV),\n\t\tCallNonvirtualIntMethodA: Some(native::CallNonvirtualIntMethodA),\n\t\tCallNonvirtualLongMethod: Some(native::CallNonvirtualLongMethod),\n\t\tCallNonvirtualLongMethodV: Some(native::CallNonvirtualLongMethodV),\n\t\tCallNonvirtualLongMethodA: Some(native::CallNonvirtualLongMethodA),\n\t\tCallNonvirtualFloatMethod: Some(native::CallNonvirtualFloatMethod),\n\t\tCallNonvirtualFloatMethodV: Some(native::CallNonvirtualFloatMethodV),\n\t\tCallNonvirtualFloatMethodA: Some(native::CallNonvirtualFloatMethodA),\n\t\tCallNonvirtualDoubleMethod: Some(native::CallNonvirtualDoubleMethod),\n\t\tCallNonvirtualDoubleMethodV: Some(native::CallNonvirtualDoubleMethodV),\n\t\tCallNonvirtualDoubleMethodA: Some(native::CallNonvirtualDoubleMethodA),\n\t\tCallNonvirtualVoidMethod: Some(native::CallNonvirtualVoidMethod),\n\t\tCallNonvirtualVoidMethodV: Some(native::CallNonvirtualVoidMethodV),\n\t\tCallNonvirtualVoidMethodA: Some(native::CallNonvirtualVoidMethodA),\n\t\tGetFieldID: Some(native::GetFieldID),\n\t\tGetObjectField: Some(native::GetObjectField),\n\t\tGetBooleanField: Some(native::GetBooleanField),\n\t\tGetByteField: Some(native::GetByteField),\n\t\tGetCharField: Some(native::GetCharField),\n\t\tGetShortField: Some(native::GetShortField),\n\t\tGetIntField: Some(native::GetIntField),\n\t\tGetLongField: Some(native::GetLongField),\n\t\tGetFloatField: Some(native::GetFloatField),\n\t\tGetDoubleField: Some(native::GetDoubleField),\n\t\tSetObjectField: Some(native::SetObjectField),\n\t\tSetBooleanField: Some(native::SetBooleanField),\n\t\tSetByteField: Some(native::SetByteField),\n\t\tSetCharField: Some(native::SetCharField),\n\t\tSetShortField: Some(native::SetShortField),\n\t\tSetIntField: Some(native::SetIntField),\n\t\tSetLongField: Some(native::SetLongField),\n\t\tSetFloatField: Some(native::SetFloatField),\n\t\tSetDoubleField: Some(native::SetDoubleField),\n\t\tGetStaticMethodID: Some(native::GetStaticMethodID),\n\t\tCallStaticObjectMethod: Some(native::CallStaticObjectMethod),\n\t\tCallStaticObjectMethodV: Some(native::CallStaticObjectMethodV),\n\t\tCallStaticObjectMethodA: Some(native::CallStaticObjectMethodA),\n\t\tCallStaticBooleanMethod: Some(native::CallStaticBooleanMethod),\n\t\tCallStaticBooleanMethodV: Some(native::CallStaticBooleanMethodV),\n\t\tCallStaticBooleanMethodA: Some(native::CallStaticBooleanMethodA),\n\t\tCallStaticByteMethod: Some(native::CallStaticByteMethod),\n\t\tCallStaticByteMethodV: Some(native::CallStaticByteMethodV),\n\t\tCallStaticByteMethodA: Some(native::CallStaticByteMethodA),\n\t\tCallStaticCharMethod: Some(native::CallStaticCharMethod),\n\t\tCallStaticCharMethodV: Some(native::CallStaticCharMethodV),\n\t\tCallStaticCharMethodA: Some(native::CallStaticCharMethodA),\n\t\tCallStaticShortMethod: Some(native::CallStaticShortMethod),\n\t\tCallStaticShortMethodV: Some(native::CallStaticShortMethodV),\n\t\tCallStaticShortMethodA: Some(native::CallStaticShortMethodA),\n\t\tCallStaticIntMethod: Some(native::CallStaticIntMethod),\n\t\tCallStaticIntMethodV: Some(native::CallStaticIntMethodV),\n\t\tCallStaticIntMethodA: Some(native::CallStaticIntMethodA),\n\t\tCallStaticLongMethod: Some(native::CallStaticLongMethod),\n\t\tCallStaticLongMethodV: Some(native::CallStaticLongMethodV),\n\t\tCallStaticLongMethodA: Some(native::CallStaticLongMethodA),\n\t\tCallStaticFloatMethod: Some(native::CallStaticFloatMethod),\n\t\tCallStaticFloatMethodV: Some(native::CallStaticFloatMethodV),\n\t\tCallStaticFloatMethodA: Some(native::CallStaticFloatMethodA),\n\t\tCallStaticDoubleMethod: Some(native::CallStaticDoubleMethod),\n\t\tCallStaticDoubleMethodV: Some(native::CallStaticDoubleMethodV),\n\t\tCallStaticDoubleMethodA: Some(native::CallStaticDoubleMethodA),\n\t\tCallStaticVoidMethod: Some(native::CallStaticVoidMethod),\n\t\tCallStaticVoidMethodV: Some(native::CallStaticVoidMethodV),\n\t\tCallStaticVoidMethodA: Some(native::CallStaticVoidMethodA),\n\t\tGetStaticFieldID: Some(native::GetStaticFieldID),\n\t\tGetStaticObjectField: Some(native::GetStaticObjectField),\n\t\tGetStaticBooleanField: Some(native::GetStaticBooleanField),\n\t\tGetStaticByteField: Some(native::GetStaticByteField),\n\t\tGetStaticCharField: Some(native::GetStaticCharField),\n\t\tGetStaticShortField: Some(native::GetStaticShortField),\n\t\tGetStaticIntField: Some(native::GetStaticIntField),\n\t\tGetStaticLongField: Some(native::GetStaticLongField),\n\t\tGetStaticFloatField: Some(native::GetStaticFloatField),\n\t\tGetStaticDoubleField: Some(native::GetStaticDoubleField),\n\t\tSetStaticObjectField: Some(native::SetStaticObjectField),\n\t\tSetStaticBooleanField: Some(native::SetStaticBooleanField),\n\t\tSetStaticByteField: Some(native::SetStaticByteField),\n\t\tSetStaticCharField: Some(native::SetStaticCharField),\n\t\tSetStaticShortField: Some(native::SetStaticShortField),\n\t\tSetStaticIntField: Some(native::SetStaticIntField),\n\t\tSetStaticLongField: Some(native::SetStaticLongField),\n\t\tSetStaticFloatField: Some(native::SetStaticFloatField),\n\t\tSetStaticDoubleField: Some(native::SetStaticDoubleField),\n\t\tNewString: Some(native::NewString),\n\t\tGetStringLength: Some(native::GetStringLength),\n\t\tGetStringChars: Some(native::GetStringChars),\n\t\tReleaseStringChars: Some(native::ReleaseStringChars),\n\t\tNewStringUTF: Some(native::NewStringUTF),\n\t\tGetStringUTFLength: Some(native::GetStringUTFLength),\n\t\tGetStringUTFChars: Some(native::GetStringUTFChars),\n\t\tReleaseStringUTFChars: Some(native::ReleaseStringUTFChars),\n\t\tGetArrayLength: Some(native::GetArrayLength),\n\t\tNewObjectArray: Some(native::NewObjectArray),\n\t\tGetObjectArrayElement: Some(native::GetObjectArrayElement),\n\t\tSetObjectArrayElement: Some(native::SetObjectArrayElement),\n\t\tNewBooleanArray: Some(native::NewBooleanArray),\n\t\tNewByteArray: Some(native::NewByteArray),\n\t\tNewCharArray: Some(native::NewCharArray),\n\t\tNewShortArray: Some(native::NewShortArray),\n\t\tNewIntArray: Some(native::NewIntArray),\n\t\tNewLongArray: Some(native::NewLongArray),\n\t\tNewFloatArray: Some(native::NewFloatArray),\n\t\tNewDoubleArray: Some(native::NewDoubleArray),\n\t\tGetBooleanArrayElements: Some(native::GetBooleanArrayElements),\n\t\tGetByteArrayElements: Some(native::GetByteArrayElements),\n\t\tGetCharArrayElements: Some(native::GetCharArrayElements),\n\t\tGetShortArrayElements: Some(native::GetShortArrayElements),\n\t\tGetIntArrayElements: Some(native::GetIntArrayElements),\n\t\tGetLongArrayElements: Some(native::GetLongArrayElements),\n\t\tGetFloatArrayElements: Some(native::GetFloatArrayElements),\n\t\tGetDoubleArrayElements: Some(native::GetDoubleArrayElements),\n\t\tReleaseBooleanArrayElements: Some(native::ReleaseBooleanArrayElements),\n\t\tReleaseByteArrayElements: Some(native::ReleaseByteArrayElements),\n\t\tReleaseCharArrayElements: Some(native::ReleaseCharArrayElements),\n\t\tReleaseShortArrayElements: Some(native::ReleaseShortArrayElements),\n\t\tReleaseIntArrayElements: Some(native::ReleaseIntArrayElements),\n\t\tReleaseLongArrayElements: Some(native::ReleaseLongArrayElements),\n\t\tReleaseFloatArrayElements: Some(native::ReleaseFloatArrayElements),\n\t\tReleaseDoubleArrayElements: Some(native::ReleaseDoubleArrayElements),\n\t\tGetBooleanArrayRegion: Some(native::GetBooleanArrayRegion),\n\t\tGetByteArrayRegion: Some(native::GetByteArrayRegion),\n\t\tGetCharArrayRegion: Some(native::GetCharArrayRegion),\n\t\tGetShortArrayRegion: Some(native::GetShortArrayRegion),\n\t\tGetIntArrayRegion: Some(native::GetIntArrayRegion),\n\t\tGetLongArrayRegion: Some(native::GetLongArrayRegion),\n\t\tGetFloatArrayRegion: Some(native::GetFloatArrayRegion),\n\t\tGetDoubleArrayRegion: Some(native::GetDoubleArrayRegion),\n\t\tSetBooleanArrayRegion: Some(native::SetBooleanArrayRegion),\n\t\tSetByteArrayRegion: Some(native::SetByteArrayRegion),\n\t\tSetCharArrayRegion: Some(native::SetCharArrayRegion),\n\t\tSetShortArrayRegion: Some(native::SetShortArrayRegion),\n\t\tSetIntArrayRegion: Some(native::SetIntArrayRegion),\n\t\tSetLongArrayRegion: Some(native::SetLongArrayRegion),\n\t\tSetFloatArrayRegion: Some(native::SetFloatArrayRegion),\n\t\tSetDoubleArrayRegion: Some(native::SetDoubleArrayRegion),\n\t\tRegisterNatives: Some(native::RegisterNatives),\n\t\tUnregisterNatives: Some(native::UnregisterNatives),\n\t\tMonitorEnter: Some(native::MonitorEnter),\n\t\tMonitorExit: Some(native::MonitorExit),\n\t\tGetJavaVM: Some(native::GetJavaVM),\n\t\tGetStringRegion: Some(native::GetStringRegion),\n\t\tGetStringUTFRegion: Some(native::GetStringUTFRegion),\n\t\tGetPrimitiveArrayCritical: Some(native::GetPrimitiveArrayCritical),\n\t\tReleasePrimitiveArrayCritical: Some(native::ReleasePrimitiveArrayCritical),\n\t\tGetStringCritical: Some(native::GetStringCritical),\n\t\tReleaseStringCritical: Some(native::ReleaseStringCritical),\n\t\tNewWeakGlobalRef: Some(native::NewWeakGlobalRef),\n\t\tDeleteWeakGlobalRef: Some(native::DeleteWeakGlobalRef),\n\t\tExceptionCheck: Some(native::ExceptionCheck),\n\t\tNewDirectByteBuffer: Some(native::NewDirectByteBuffer),\n\t\tGetDirectBufferAddress: Some(native::GetDirectBufferAddress),\n\t\tGetDirectBufferCapacity: Some(native::GetDirectBufferCapacity),\n\t\tGetObjectRefType: Some(native::GetObjectRefType),\n\t})) as *mut core::ffi::c_void;\n\t0\n}\nunsafe extern \"system\" fn AttachCurrentThreadAsDaemon(\n\t_vm: *mut JavaVM,\n\t_penv: *mut *mut c_void,\n\t_args: *mut c_void,\n) -> jint {\n\ttodo!();\n}\n\n#[repr(C)]\nstruct JavaVMOption {\n\toption_string: *const libc::c_void,\n\textra_info: *const libc::c_void,\n}\nimpl JavaVMOption {\n\tfn string(&self) -> &std::ffi::CStr {\n\t\tunsafe { std::ffi::CStr::from_ptr(self.option_string as *const _) }\n\t}\n}\nimpl std::fmt::Debug for JavaVMOption {\n\tfn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {\n\t\tfmt.debug_struct(\"JavaVMOption\")\n\t\t\t.field(\"option_string\", &self.string())\n\t\t\t.finish()\n\t}\n}\n\n#[repr(C)]\nstruct JavaVMInitArgs {\n\tversion: jint,\n\n\tn_options: jint,\n\toptions: *const JavaVMOption,\n\tignore_unrecognized: jboolean,\n}\nimpl JavaVMInitArgs {\n\tfn options(&self) -> &[JavaVMOption] {\n\t\tunsafe { std::slice::from_raw_parts(self.options, self.n_options as usize) }\n\t}\n}\n\nimpl std::fmt::Debug for JavaVMInitArgs {\n\tfn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {\n\t\tfmt.debug_struct(\"JavaVMInitArgs\")\n\t\t\t.field(\"version\", &self.version)\n\t\t\t.field(\"ignore_unrecognized\", &self.ignore_unrecognized)\n\t\t\t.field(\"options\", &self.options())\n\t\t\t.finish()\n\t}\n}\n\n#[no_mangle]\nextern \"C\" fn JNI_CreateJavaVM(\n\tpvm: *mut *mut JavaVM,\n\tpenv: *mut *mut c_void,\n\targs: *const JavaVMInitArgs,\n) -> jint {\n\tlet mut lock = JVM.lock().expect(\"jvm lock\");\n\t// Can't have multiple VMs per process\n\tif lock.is_some() {\n\t\t-1\n\t} else {\n\t\tuse std::ptr::null_mut;\n\t\tvm::native::init();\n\t\tvm::oop::init();\n\t\tvm::runtime::init();\n\t\t// To be run from jre dir\n\t\tvm::runtime::add_class_path(\"./lib/rt.jar\");\n\t\tvm::runtime::add_class_path(\"./lib/jsse.jar\");\n\t\tlet args = unsafe { &*args };\n\t\t// TODO: Pass to jvm\n\t\tlet mut properties: std::collections::HashMap<String, String> =\n\t\t\tstd::collections::HashMap::new();\n\t\tfor option in args.options() {\n\t\t\tlet option: String = option.string().to_string_lossy().into();\n\t\t\tif option.starts_with(\"-D\") {\n\t\t\t\tlet idx = option.find(\"=\").expect(\"bad property argument format\");\n\t\t\t\tproperties.insert(option[2..idx].to_owned(), option[idx..].to_owned());\n\t\t\t} else if args.ignore_unrecognized == 0 {\n\t\t\t\tpanic!(\"unknown option: {}\", option);\n\t\t\t}\n\t\t}\n\n\t\tlet holder = VMHolder {\n\t\t\tjvm: Box::new(JNIInvokeInterface_ {\n\t\t\t\t// We can use reserved fields for implementation details\n\t\t\t\treserved0: null_mut(),\n\t\t\t\treserved1: null_mut(),\n\t\t\t\treserved2: null_mut(),\n\t\t\t\tDestroyJavaVM: Some(DestroyJavaVM),\n\t\t\t\tAttachCurrentThread: Some(AttachCurrentThread),\n\t\t\t\tDetachCurrentThread: Some(DetachCurrentThread),\n\t\t\t\tGetEnv: Some(GetEnv),\n\t\t\t\tAttachCurrentThreadAsDaemon: Some(AttachCurrentThreadAsDaemon),\n\t\t\t}),\n\t\t};\n\t\tunsafe {\n\t\t\t*pvm = Box::into_raw(Box::new(holder.inner()));\n\t\t\tholder.jvm.GetEnv.unwrap()(&mut holder.inner(), penv, 0);\n\t\t}\n\t\tlock.replace(holder);\n\t\t0\n\t}\n}\n\n#[no_mangle]\nextern \"C\" fn JNI_GetCreatedJavaVMs(\n\tvm_buf: *mut *mut JavaVM,\n\tbuf_len: jsize,\n\tn_vms: *mut jsize,\n) -> jint {\n\tif buf_len >= 1 {\n\t\tlet lock = JVM.lock().expect(\"jvm lock\");\n\t\tif let Some(ref holder) = lock.as_ref() {\n\t\t\tunsafe {\n\t\t\t\t*vm_buf = Box::into_raw(Box::new(holder.jvm.as_ref()));\n\t\t\t\t*n_vms = 1;\n\t\t\t}\n\t\t} else {\n\t\t\tunsafe {\n\t\t\t\t*n_vms = 0;\n\t\t\t}\n\t\t}\n\t\t1\n\t} else {\n\t\tunsafe {\n\t\t\t*n_vms = 0;\n\t\t};\n\t\t0\n\t}\n}\n"
  },
  {
    "path": "libjvm/src/lib.rs",
    "content": "#![feature(c_variadic)]\n\npub mod invocation;\npub mod native;\npub mod private;\npub mod util;\n"
  },
  {
    "path": "libjvm/src/native.rs",
    "content": "#![allow(non_snake_case)]\n#![allow(unused_variables)]\n#![allow(unused_imports)]\n\nuse jni_sys::{\n\tjarray, jboolean, jbooleanArray, jbyte, jbyteArray, jchar, jcharArray, jclass, jdouble,\n\tjdoubleArray, jfieldID, jfloat, jfloatArray, jint, jintArray, jlong, jlongArray, jmethodID,\n\tjobject, jobjectArray, jobjectRefType, jshort, jshortArray, jsize, jstring, jthrowable, jvalue,\n\tjweak, JNIEnv, JNIInvokeInterface_, JNINativeInterface_, JNINativeMethod, JavaVM,\n};\nuse libc::{c_char, c_void};\npub type va_list = *mut c_void;\n\npub unsafe extern \"system\" fn GetVersion(env: *mut JNIEnv) -> jint {\n\ttodo!();\n}\npub unsafe extern \"system\" fn DefineClass(\n\tenv: *mut JNIEnv,\n\tname: *const c_char,\n\tloader: jobject,\n\tbuf: *const jbyte,\n\tlen: jsize,\n) -> jclass {\n\ttodo!();\n}\npub unsafe extern \"system\" fn FindClass(env: *mut JNIEnv, name: *const c_char) -> jclass {\n\ttodo!();\n}\npub unsafe extern \"system\" fn FromReflectedMethod(env: *mut JNIEnv, method: jobject) -> jmethodID {\n\ttodo!();\n}\npub unsafe extern \"system\" fn FromReflectedField(env: *mut JNIEnv, field: jobject) -> jfieldID {\n\ttodo!();\n}\npub unsafe extern \"system\" fn ToReflectedMethod(\n\tenv: *mut JNIEnv,\n\tcls: jclass,\n\tmethodID: jmethodID,\n\tisStatic: jboolean,\n) -> jobject {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetSuperclass(env: *mut JNIEnv, sub: jclass) -> jclass {\n\ttodo!();\n}\npub unsafe extern \"system\" fn IsAssignableFrom(\n\tenv: *mut JNIEnv,\n\tsub: jclass,\n\tsup: jclass,\n) -> jboolean {\n\ttodo!();\n}\npub unsafe extern \"system\" fn ToReflectedField(\n\tenv: *mut JNIEnv,\n\tcls: jclass,\n\tfieldID: jfieldID,\n\tisStatic: jboolean,\n) -> jobject {\n\ttodo!();\n}\npub unsafe extern \"system\" fn Throw(env: *mut JNIEnv, obj: jthrowable) -> jint {\n\ttodo!();\n}\npub unsafe extern \"system\" fn ThrowNew(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tmsg: *const c_char,\n) -> jint {\n\ttodo!();\n}\npub unsafe extern \"system\" fn ExceptionOccurred(env: *mut JNIEnv) -> jthrowable {\n\ttodo!();\n}\npub unsafe extern \"system\" fn ExceptionDescribe(env: *mut JNIEnv) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn ExceptionClear(env: *mut JNIEnv) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn FatalError(env: *mut JNIEnv, msg: *const c_char) -> ! {\n\ttodo!();\n}\npub unsafe extern \"system\" fn PushLocalFrame(env: *mut JNIEnv, capacity: jint) -> jint {\n\ttodo!();\n}\npub unsafe extern \"system\" fn PopLocalFrame(env: *mut JNIEnv, result: jobject) -> jobject {\n\ttodo!();\n}\npub unsafe extern \"system\" fn NewGlobalRef(env: *mut JNIEnv, lobj: jobject) -> jobject {\n\ttodo!();\n}\npub unsafe extern \"system\" fn DeleteGlobalRef(env: *mut JNIEnv, gref: jobject) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn DeleteLocalRef(env: *mut JNIEnv, obj: jobject) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn IsSameObject(\n\tenv: *mut JNIEnv,\n\tobj1: jobject,\n\tobj2: jobject,\n) -> jboolean {\n\ttodo!();\n}\npub unsafe extern \"system\" fn NewLocalRef(env: *mut JNIEnv, ref_: jobject) -> jobject {\n\ttodo!();\n}\npub unsafe extern \"system\" fn EnsureLocalCapacity(env: *mut JNIEnv, capacity: jint) -> jint {\n\ttodo!();\n}\npub unsafe extern \"system\" fn AllocObject(env: *mut JNIEnv, clazz: jclass) -> jobject {\n\ttodo!();\n}\npub unsafe extern \"C\" fn NewObject(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\t...\n) -> jobject {\n\ttodo!();\n}\npub unsafe extern \"system\" fn NewObjectV(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: va_list,\n) -> jobject {\n\ttodo!();\n}\npub unsafe extern \"system\" fn NewObjectA(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: *const jvalue,\n) -> jobject {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetObjectClass(env: *mut JNIEnv, obj: jobject) -> jclass {\n\ttodo!();\n}\npub unsafe extern \"system\" fn IsInstanceOf(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tclazz: jclass,\n) -> jboolean {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetMethodID(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tname: *const c_char,\n\tsig: *const c_char,\n) -> jmethodID {\n\ttodo!();\n}\npub unsafe extern \"C\" fn CallObjectMethod(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tmethodID: jmethodID,\n\t...\n) -> jobject {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallObjectMethodV(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tmethodID: jmethodID,\n\targs: va_list,\n) -> jobject {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallObjectMethodA(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tmethodID: jmethodID,\n\targs: *const jvalue,\n) -> jobject {\n\ttodo!();\n}\npub unsafe extern \"C\" fn CallBooleanMethod(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tmethodID: jmethodID,\n\t...\n) -> jboolean {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallBooleanMethodV(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tmethodID: jmethodID,\n\targs: va_list,\n) -> jboolean {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallBooleanMethodA(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tmethodID: jmethodID,\n\targs: *const jvalue,\n) -> jboolean {\n\ttodo!();\n}\npub unsafe extern \"C\" fn CallByteMethod(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tmethodID: jmethodID,\n\t...\n) -> jbyte {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallByteMethodV(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tmethodID: jmethodID,\n\targs: va_list,\n) -> jbyte {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallByteMethodA(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tmethodID: jmethodID,\n\targs: *const jvalue,\n) -> jbyte {\n\ttodo!();\n}\npub unsafe extern \"C\" fn CallCharMethod(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tmethodID: jmethodID,\n\t...\n) -> jchar {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallCharMethodV(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tmethodID: jmethodID,\n\targs: va_list,\n) -> jchar {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallCharMethodA(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tmethodID: jmethodID,\n\targs: *const jvalue,\n) -> jchar {\n\ttodo!();\n}\npub unsafe extern \"C\" fn CallShortMethod(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tmethodID: jmethodID,\n\t...\n) -> jshort {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallShortMethodV(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tmethodID: jmethodID,\n\targs: va_list,\n) -> jshort {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallShortMethodA(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tmethodID: jmethodID,\n\targs: *const jvalue,\n) -> jshort {\n\ttodo!();\n}\npub unsafe extern \"C\" fn CallIntMethod(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tmethodID: jmethodID,\n\t...\n) -> jint {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallIntMethodV(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tmethodID: jmethodID,\n\targs: va_list,\n) -> jint {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallIntMethodA(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tmethodID: jmethodID,\n\targs: *const jvalue,\n) -> jint {\n\ttodo!();\n}\npub unsafe extern \"C\" fn CallLongMethod(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tmethodID: jmethodID,\n\t...\n) -> jlong {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallLongMethodV(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tmethodID: jmethodID,\n\targs: va_list,\n) -> jlong {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallLongMethodA(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tmethodID: jmethodID,\n\targs: *const jvalue,\n) -> jlong {\n\ttodo!();\n}\npub unsafe extern \"C\" fn CallFloatMethod(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tmethodID: jmethodID,\n\t...\n) -> jfloat {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallFloatMethodV(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tmethodID: jmethodID,\n\targs: va_list,\n) -> jfloat {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallFloatMethodA(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tmethodID: jmethodID,\n\targs: *const jvalue,\n) -> jfloat {\n\ttodo!();\n}\npub unsafe extern \"C\" fn CallDoubleMethod(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tmethodID: jmethodID,\n\t...\n) -> jdouble {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallDoubleMethodV(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tmethodID: jmethodID,\n\targs: va_list,\n) -> jdouble {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallDoubleMethodA(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tmethodID: jmethodID,\n\targs: *const jvalue,\n) -> jdouble {\n\ttodo!();\n}\npub unsafe extern \"C\" fn CallVoidMethod(env: *mut JNIEnv, obj: jobject, methodID: jmethodID, ...) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallVoidMethodV(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tmethodID: jmethodID,\n\targs: va_list,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallVoidMethodA(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tmethodID: jmethodID,\n\targs: *const jvalue,\n) {\n\ttodo!();\n}\npub unsafe extern \"C\" fn CallNonvirtualObjectMethod(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\t...\n) -> jobject {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallNonvirtualObjectMethodV(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: va_list,\n) -> jobject {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallNonvirtualObjectMethodA(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: *const jvalue,\n) -> jobject {\n\ttodo!();\n}\npub unsafe extern \"C\" fn CallNonvirtualBooleanMethod(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\t...\n) -> jboolean {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallNonvirtualBooleanMethodV(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: va_list,\n) -> jboolean {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallNonvirtualBooleanMethodA(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: *const jvalue,\n) -> jboolean {\n\ttodo!();\n}\npub unsafe extern \"C\" fn CallNonvirtualByteMethod(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\t...\n) -> jbyte {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallNonvirtualByteMethodV(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: va_list,\n) -> jbyte {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallNonvirtualByteMethodA(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: *const jvalue,\n) -> jbyte {\n\ttodo!();\n}\npub unsafe extern \"C\" fn CallNonvirtualCharMethod(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\t...\n) -> jchar {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallNonvirtualCharMethodV(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: va_list,\n) -> jchar {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallNonvirtualCharMethodA(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: *const jvalue,\n) -> jchar {\n\ttodo!();\n}\npub unsafe extern \"C\" fn CallNonvirtualShortMethod(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\t...\n) -> jshort {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallNonvirtualShortMethodV(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: va_list,\n) -> jshort {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallNonvirtualShortMethodA(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: *const jvalue,\n) -> jshort {\n\ttodo!();\n}\npub unsafe extern \"C\" fn CallNonvirtualIntMethod(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\t...\n) -> jint {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallNonvirtualIntMethodV(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: va_list,\n) -> jint {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallNonvirtualIntMethodA(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: *const jvalue,\n) -> jint {\n\ttodo!();\n}\npub unsafe extern \"C\" fn CallNonvirtualLongMethod(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\t...\n) -> jlong {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallNonvirtualLongMethodV(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: va_list,\n) -> jlong {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallNonvirtualLongMethodA(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: *const jvalue,\n) -> jlong {\n\ttodo!();\n}\npub unsafe extern \"C\" fn CallNonvirtualFloatMethod(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\t...\n) -> jfloat {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallNonvirtualFloatMethodV(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: va_list,\n) -> jfloat {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallNonvirtualFloatMethodA(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: *const jvalue,\n) -> jfloat {\n\ttodo!();\n}\npub unsafe extern \"C\" fn CallNonvirtualDoubleMethod(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\t...\n) -> jdouble {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallNonvirtualDoubleMethodV(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: va_list,\n) -> jdouble {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallNonvirtualDoubleMethodA(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: *const jvalue,\n) -> jdouble {\n\ttodo!();\n}\npub unsafe extern \"C\" fn CallNonvirtualVoidMethod(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\t...\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallNonvirtualVoidMethodV(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: va_list,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallNonvirtualVoidMethodA(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: *const jvalue,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetFieldID(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tname: *const c_char,\n\tsig: *const c_char,\n) -> jfieldID {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetObjectField(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tfieldID: jfieldID,\n) -> jobject {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetBooleanField(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tfieldID: jfieldID,\n) -> jboolean {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetByteField(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tfieldID: jfieldID,\n) -> jbyte {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetCharField(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tfieldID: jfieldID,\n) -> jchar {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetShortField(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tfieldID: jfieldID,\n) -> jshort {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetIntField(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tfieldID: jfieldID,\n) -> jint {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetLongField(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tfieldID: jfieldID,\n) -> jlong {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetFloatField(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tfieldID: jfieldID,\n) -> jfloat {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetDoubleField(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tfieldID: jfieldID,\n) -> jdouble {\n\ttodo!();\n}\npub unsafe extern \"system\" fn SetObjectField(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tfieldID: jfieldID,\n\tval: jobject,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn SetBooleanField(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tfieldID: jfieldID,\n\tval: jboolean,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn SetByteField(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tfieldID: jfieldID,\n\tval: jbyte,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn SetCharField(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tfieldID: jfieldID,\n\tval: jchar,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn SetShortField(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tfieldID: jfieldID,\n\tval: jshort,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn SetIntField(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tfieldID: jfieldID,\n\tval: jint,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn SetLongField(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tfieldID: jfieldID,\n\tval: jlong,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn SetFloatField(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tfieldID: jfieldID,\n\tval: jfloat,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn SetDoubleField(\n\tenv: *mut JNIEnv,\n\tobj: jobject,\n\tfieldID: jfieldID,\n\tval: jdouble,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetStaticMethodID(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tname: *const c_char,\n\tsig: *const c_char,\n) -> jmethodID {\n\ttodo!();\n}\npub unsafe extern \"C\" fn CallStaticObjectMethod(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\t...\n) -> jobject {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallStaticObjectMethodV(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: va_list,\n) -> jobject {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallStaticObjectMethodA(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: *const jvalue,\n) -> jobject {\n\ttodo!();\n}\npub unsafe extern \"C\" fn CallStaticBooleanMethod(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\t...\n) -> jboolean {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallStaticBooleanMethodV(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: va_list,\n) -> jboolean {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallStaticBooleanMethodA(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: *const jvalue,\n) -> jboolean {\n\ttodo!();\n}\npub unsafe extern \"C\" fn CallStaticByteMethod(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\t...\n) -> jbyte {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallStaticByteMethodV(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: va_list,\n) -> jbyte {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallStaticByteMethodA(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: *const jvalue,\n) -> jbyte {\n\ttodo!();\n}\npub unsafe extern \"C\" fn CallStaticCharMethod(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\t...\n) -> jchar {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallStaticCharMethodV(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: va_list,\n) -> jchar {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallStaticCharMethodA(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: *const jvalue,\n) -> jchar {\n\ttodo!();\n}\npub unsafe extern \"C\" fn CallStaticShortMethod(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\t...\n) -> jshort {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallStaticShortMethodV(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: va_list,\n) -> jshort {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallStaticShortMethodA(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: *const jvalue,\n) -> jshort {\n\ttodo!();\n}\npub unsafe extern \"C\" fn CallStaticIntMethod(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\t...\n) -> jint {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallStaticIntMethodV(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: va_list,\n) -> jint {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallStaticIntMethodA(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: *const jvalue,\n) -> jint {\n\ttodo!();\n}\npub unsafe extern \"C\" fn CallStaticLongMethod(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\t...\n) -> jlong {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallStaticLongMethodV(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: va_list,\n) -> jlong {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallStaticLongMethodA(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: *const jvalue,\n) -> jlong {\n\ttodo!();\n}\npub unsafe extern \"C\" fn CallStaticFloatMethod(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\t...\n) -> jfloat {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallStaticFloatMethodV(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: va_list,\n) -> jfloat {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallStaticFloatMethodA(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: *const jvalue,\n) -> jfloat {\n\ttodo!();\n}\npub unsafe extern \"C\" fn CallStaticDoubleMethod(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\t...\n) -> jdouble {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallStaticDoubleMethodV(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: va_list,\n) -> jdouble {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallStaticDoubleMethodA(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tmethodID: jmethodID,\n\targs: *const jvalue,\n) -> jdouble {\n\ttodo!();\n}\npub unsafe extern \"C\" fn CallStaticVoidMethod(\n\tenv: *mut JNIEnv,\n\tcls: jclass,\n\tmethodID: jmethodID,\n\t...\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallStaticVoidMethodV(\n\tenv: *mut JNIEnv,\n\tcls: jclass,\n\tmethodID: jmethodID,\n\targs: va_list,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn CallStaticVoidMethodA(\n\tenv: *mut JNIEnv,\n\tcls: jclass,\n\tmethodID: jmethodID,\n\targs: *const jvalue,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetStaticFieldID(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tname: *const c_char,\n\tsig: *const c_char,\n) -> jfieldID {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetStaticObjectField(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tfieldID: jfieldID,\n) -> jobject {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetStaticBooleanField(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tfieldID: jfieldID,\n) -> jboolean {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetStaticByteField(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tfieldID: jfieldID,\n) -> jbyte {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetStaticCharField(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tfieldID: jfieldID,\n) -> jchar {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetStaticShortField(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tfieldID: jfieldID,\n) -> jshort {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetStaticIntField(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tfieldID: jfieldID,\n) -> jint {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetStaticLongField(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tfieldID: jfieldID,\n) -> jlong {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetStaticFloatField(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tfieldID: jfieldID,\n) -> jfloat {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetStaticDoubleField(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tfieldID: jfieldID,\n) -> jdouble {\n\ttodo!();\n}\npub unsafe extern \"system\" fn SetStaticObjectField(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tfieldID: jfieldID,\n\tvalue: jobject,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn SetStaticBooleanField(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tfieldID: jfieldID,\n\tvalue: jboolean,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn SetStaticByteField(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tfieldID: jfieldID,\n\tvalue: jbyte,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn SetStaticCharField(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tfieldID: jfieldID,\n\tvalue: jchar,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn SetStaticShortField(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tfieldID: jfieldID,\n\tvalue: jshort,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn SetStaticIntField(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tfieldID: jfieldID,\n\tvalue: jint,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn SetStaticLongField(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tfieldID: jfieldID,\n\tvalue: jlong,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn SetStaticFloatField(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tfieldID: jfieldID,\n\tvalue: jfloat,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn SetStaticDoubleField(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tfieldID: jfieldID,\n\tvalue: jdouble,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn NewString(\n\tenv: *mut JNIEnv,\n\tunicode: *const jchar,\n\tlen: jsize,\n) -> jstring {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetStringLength(env: *mut JNIEnv, str: jstring) -> jsize {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetStringChars(\n\tenv: *mut JNIEnv,\n\tstr: jstring,\n\tisCopy: *mut jboolean,\n) -> *const jchar {\n\ttodo!();\n}\npub unsafe extern \"system\" fn ReleaseStringChars(\n\tenv: *mut JNIEnv,\n\tstr: jstring,\n\tchars: *const jchar,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn NewStringUTF(env: *mut JNIEnv, utf: *const c_char) -> jstring {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetStringUTFLength(env: *mut JNIEnv, str: jstring) -> jsize {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetStringUTFChars(\n\tenv: *mut JNIEnv,\n\tstr: jstring,\n\tisCopy: *mut jboolean,\n) -> *const c_char {\n\ttodo!();\n}\npub unsafe extern \"system\" fn ReleaseStringUTFChars(\n\tenv: *mut JNIEnv,\n\tstr: jstring,\n\tchars: *const c_char,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetArrayLength(env: *mut JNIEnv, array: jarray) -> jsize {\n\ttodo!();\n}\npub unsafe extern \"system\" fn NewObjectArray(\n\tenv: *mut JNIEnv,\n\tlen: jsize,\n\tclazz: jclass,\n\tinit: jobject,\n) -> jobjectArray {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetObjectArrayElement(\n\tenv: *mut JNIEnv,\n\tarray: jobjectArray,\n\tindex: jsize,\n) -> jobject {\n\ttodo!();\n}\npub unsafe extern \"system\" fn SetObjectArrayElement(\n\tenv: *mut JNIEnv,\n\tarray: jobjectArray,\n\tindex: jsize,\n\tval: jobject,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn NewBooleanArray(env: *mut JNIEnv, len: jsize) -> jbooleanArray {\n\ttodo!();\n}\npub unsafe extern \"system\" fn NewByteArray(env: *mut JNIEnv, len: jsize) -> jbyteArray {\n\ttodo!();\n}\npub unsafe extern \"system\" fn NewCharArray(env: *mut JNIEnv, len: jsize) -> jcharArray {\n\ttodo!();\n}\npub unsafe extern \"system\" fn NewShortArray(env: *mut JNIEnv, len: jsize) -> jshortArray {\n\ttodo!();\n}\npub unsafe extern \"system\" fn NewIntArray(env: *mut JNIEnv, len: jsize) -> jintArray {\n\ttodo!();\n}\npub unsafe extern \"system\" fn NewLongArray(env: *mut JNIEnv, len: jsize) -> jlongArray {\n\ttodo!();\n}\npub unsafe extern \"system\" fn NewFloatArray(env: *mut JNIEnv, len: jsize) -> jfloatArray {\n\ttodo!();\n}\npub unsafe extern \"system\" fn NewDoubleArray(env: *mut JNIEnv, len: jsize) -> jdoubleArray {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetBooleanArrayElements(\n\tenv: *mut JNIEnv,\n\tarray: jbooleanArray,\n\tisCopy: *mut jboolean,\n) -> *mut jboolean {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetByteArrayElements(\n\tenv: *mut JNIEnv,\n\tarray: jbyteArray,\n\tisCopy: *mut jboolean,\n) -> *mut jbyte {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetCharArrayElements(\n\tenv: *mut JNIEnv,\n\tarray: jcharArray,\n\tisCopy: *mut jboolean,\n) -> *mut jchar {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetShortArrayElements(\n\tenv: *mut JNIEnv,\n\tarray: jshortArray,\n\tisCopy: *mut jboolean,\n) -> *mut jshort {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetIntArrayElements(\n\tenv: *mut JNIEnv,\n\tarray: jintArray,\n\tisCopy: *mut jboolean,\n) -> *mut jint {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetLongArrayElements(\n\tenv: *mut JNIEnv,\n\tarray: jlongArray,\n\tisCopy: *mut jboolean,\n) -> *mut jlong {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetFloatArrayElements(\n\tenv: *mut JNIEnv,\n\tarray: jfloatArray,\n\tisCopy: *mut jboolean,\n) -> *mut jfloat {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetDoubleArrayElements(\n\tenv: *mut JNIEnv,\n\tarray: jdoubleArray,\n\tisCopy: *mut jboolean,\n) -> *mut jdouble {\n\ttodo!();\n}\npub unsafe extern \"system\" fn ReleaseBooleanArrayElements(\n\tenv: *mut JNIEnv,\n\tarray: jbooleanArray,\n\telems: *mut jboolean,\n\tmode: jint,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn ReleaseByteArrayElements(\n\tenv: *mut JNIEnv,\n\tarray: jbyteArray,\n\telems: *mut jbyte,\n\tmode: jint,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn ReleaseCharArrayElements(\n\tenv: *mut JNIEnv,\n\tarray: jcharArray,\n\telems: *mut jchar,\n\tmode: jint,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn ReleaseShortArrayElements(\n\tenv: *mut JNIEnv,\n\tarray: jshortArray,\n\telems: *mut jshort,\n\tmode: jint,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn ReleaseIntArrayElements(\n\tenv: *mut JNIEnv,\n\tarray: jintArray,\n\telems: *mut jint,\n\tmode: jint,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn ReleaseLongArrayElements(\n\tenv: *mut JNIEnv,\n\tarray: jlongArray,\n\telems: *mut jlong,\n\tmode: jint,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn ReleaseFloatArrayElements(\n\tenv: *mut JNIEnv,\n\tarray: jfloatArray,\n\telems: *mut jfloat,\n\tmode: jint,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn ReleaseDoubleArrayElements(\n\tenv: *mut JNIEnv,\n\tarray: jdoubleArray,\n\telems: *mut jdouble,\n\tmode: jint,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetBooleanArrayRegion(\n\tenv: *mut JNIEnv,\n\tarray: jbooleanArray,\n\tstart: jsize,\n\tl: jsize,\n\tbuf: *mut jboolean,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetByteArrayRegion(\n\tenv: *mut JNIEnv,\n\tarray: jbyteArray,\n\tstart: jsize,\n\tlen: jsize,\n\tbuf: *mut jbyte,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetCharArrayRegion(\n\tenv: *mut JNIEnv,\n\tarray: jcharArray,\n\tstart: jsize,\n\tlen: jsize,\n\tbuf: *mut jchar,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetShortArrayRegion(\n\tenv: *mut JNIEnv,\n\tarray: jshortArray,\n\tstart: jsize,\n\tlen: jsize,\n\tbuf: *mut jshort,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetIntArrayRegion(\n\tenv: *mut JNIEnv,\n\tarray: jintArray,\n\tstart: jsize,\n\tlen: jsize,\n\tbuf: *mut jint,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetLongArrayRegion(\n\tenv: *mut JNIEnv,\n\tarray: jlongArray,\n\tstart: jsize,\n\tlen: jsize,\n\tbuf: *mut jlong,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetFloatArrayRegion(\n\tenv: *mut JNIEnv,\n\tarray: jfloatArray,\n\tstart: jsize,\n\tlen: jsize,\n\tbuf: *mut jfloat,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetDoubleArrayRegion(\n\tenv: *mut JNIEnv,\n\tarray: jdoubleArray,\n\tstart: jsize,\n\tlen: jsize,\n\tbuf: *mut jdouble,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn SetBooleanArrayRegion(\n\tenv: *mut JNIEnv,\n\tarray: jbooleanArray,\n\tstart: jsize,\n\tl: jsize,\n\tbuf: *const jboolean,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn SetByteArrayRegion(\n\tenv: *mut JNIEnv,\n\tarray: jbyteArray,\n\tstart: jsize,\n\tlen: jsize,\n\tbuf: *const jbyte,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn SetCharArrayRegion(\n\tenv: *mut JNIEnv,\n\tarray: jcharArray,\n\tstart: jsize,\n\tlen: jsize,\n\tbuf: *const jchar,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn SetShortArrayRegion(\n\tenv: *mut JNIEnv,\n\tarray: jshortArray,\n\tstart: jsize,\n\tlen: jsize,\n\tbuf: *const jshort,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn SetIntArrayRegion(\n\tenv: *mut JNIEnv,\n\tarray: jintArray,\n\tstart: jsize,\n\tlen: jsize,\n\tbuf: *const jint,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn SetLongArrayRegion(\n\tenv: *mut JNIEnv,\n\tarray: jlongArray,\n\tstart: jsize,\n\tlen: jsize,\n\tbuf: *const jlong,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn SetFloatArrayRegion(\n\tenv: *mut JNIEnv,\n\tarray: jfloatArray,\n\tstart: jsize,\n\tlen: jsize,\n\tbuf: *const jfloat,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn SetDoubleArrayRegion(\n\tenv: *mut JNIEnv,\n\tarray: jdoubleArray,\n\tstart: jsize,\n\tlen: jsize,\n\tbuf: *const jdouble,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn RegisterNatives(\n\tenv: *mut JNIEnv,\n\tclazz: jclass,\n\tmethods: *const JNINativeMethod,\n\tnMethods: jint,\n) -> jint {\n\ttodo!();\n}\npub unsafe extern \"system\" fn UnregisterNatives(env: *mut JNIEnv, clazz: jclass) -> jint {\n\ttodo!();\n}\npub unsafe extern \"system\" fn MonitorEnter(env: *mut JNIEnv, obj: jobject) -> jint {\n\ttodo!();\n}\npub unsafe extern \"system\" fn MonitorExit(env: *mut JNIEnv, obj: jobject) -> jint {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetJavaVM(env: *mut JNIEnv, vm: *mut *mut JavaVM) -> jint {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetStringRegion(\n\tenv: *mut JNIEnv,\n\tstr: jstring,\n\tstart: jsize,\n\tlen: jsize,\n\tbuf: *mut jchar,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetStringUTFRegion(\n\tenv: *mut JNIEnv,\n\tstr: jstring,\n\tstart: jsize,\n\tlen: jsize,\n\tbuf: *mut c_char,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetPrimitiveArrayCritical(\n\tenv: *mut JNIEnv,\n\tarray: jarray,\n\tisCopy: *mut jboolean,\n) -> *mut c_void {\n\ttodo!();\n}\npub unsafe extern \"system\" fn ReleasePrimitiveArrayCritical(\n\tenv: *mut JNIEnv,\n\tarray: jarray,\n\tcarray: *mut c_void,\n\tmode: jint,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetStringCritical(\n\tenv: *mut JNIEnv,\n\tstring: jstring,\n\tisCopy: *mut jboolean,\n) -> *const jchar {\n\ttodo!();\n}\npub unsafe extern \"system\" fn ReleaseStringCritical(\n\tenv: *mut JNIEnv,\n\tstring: jstring,\n\tcstring: *const jchar,\n) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn NewWeakGlobalRef(env: *mut JNIEnv, obj: jobject) -> jweak {\n\ttodo!();\n}\npub unsafe extern \"system\" fn DeleteWeakGlobalRef(env: *mut JNIEnv, ref_: jweak) {\n\ttodo!();\n}\npub unsafe extern \"system\" fn ExceptionCheck(env: *mut JNIEnv) -> jboolean {\n\ttodo!();\n}\npub unsafe extern \"system\" fn NewDirectByteBuffer(\n\tenv: *mut JNIEnv,\n\taddress: *mut c_void,\n\tcapacity: jlong,\n) -> jobject {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetDirectBufferAddress(\n\tenv: *mut JNIEnv,\n\tbuf: jobject,\n) -> *mut c_void {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetDirectBufferCapacity(env: *mut JNIEnv, buf: jobject) -> jlong {\n\ttodo!();\n}\npub unsafe extern \"system\" fn GetObjectRefType(env: *mut JNIEnv, obj: jobject) -> jobjectRefType {\n\ttodo!();\n}\n"
  },
  {
    "path": "libjvm/src/private.rs",
    "content": "#![allow(unused_variables)]\n\nuse jni_sys::{jclass, JNIEnv};\n\n/// Used by java launcher as entry point\n#[no_mangle]\npub unsafe extern \"system\" fn JVM_FindClassFromBootLoader(\n\tenv: *const JNIEnv,\n\tname: *const i8,\n) -> jclass {\n\tlet class_name = std::ffi::CStr::from_ptr(name);\n\tlet bytes = class_name.to_bytes();\n\tlet class = vm::runtime::require_class3(None, bytes);\n\tcrate::util::class_ref_to_jclass(class)\n}\n"
  },
  {
    "path": "libjvm/src/util.rs",
    "content": "#![allow(unused_imports)]\n\n/// Conversions between jvm and jni api\nuse jni_sys::{jclass, JNIEnv};\n\npub fn class_ref_to_jclass(class_ref: Option<vm::types::ClassRef>) -> jclass {\n\tif let Some(class_ref) = class_ref {\n\t\tclass_ref.as_ref() as *const _ as jclass\n\t} else {\n\t\tstd::ptr::null_mut()\n\t}\n}\n"
  },
  {
    "path": "note.txt",
    "content": "char\n-----------------------\nChar in Java: 16-bit unsigned integers\nchar in Rust: four bytes in size\n\n\nproblem\n----------------------\n1. System.arraycopy\n  The performance of JVM depends on arraycopy.\n\n     ArrayList<Integer> list = new ArrayList<Integer>();\n     int start = 0;\n     while (start < 50000) {\n         list.add(start++);\n     }\n\n  It's slow to run the code, but Oracle Java very quick.\n  The reason is that, invoke 'clone' for every OopRef\n  test case: $JDK_TEST/Character/CheckProp.java\n\n  Key Points:\n     a. create lots of Integer object\n     b. ArrayList inner buf, new bigger buffer when reach limit,\n       then, invoke System.arraycopy to move objects\n\n2. dynamic workers in thread pool\n  spawn & gc worker dynamic\nindicators:\n  a. system payload\n  b. worker queue\n  c. thread types (io? calculation?)\n\n\njdk\n-----------------------\nByteBuffer (along with all IntBuffer, LongBuffer, ...) are generated from X-Buffer.java.template.\n\n\nGC\n-----------------------\npaper:\nhttp://users.cecs.anu.edu.au/~steveb/downloads/pdf/rust-ismm-2016.pdf\nan example of a high performance GC impl in Rust.\n\ncodes:\nhttps://github.com/Manishearth/rust-gc\nSimple tracing (mark and sweep) garbage collector for Rust\n\n\n\nMilestones\n-----------------------\n2020.01.30\nAdd.java run successfully\n\n2020.02.01\ngithub 100 commits\n\n2020.02.09\ncode lines reach 10k\n\n2020.02.13\nHelloWorld run successfully\n\n2020.02.14\nOop::str replaced by java.lang.String\n\n2020.02.15\ngithub 200 commits, First Watchers, CertainLach, thanks!\n\n2020.02.19\nThank Rust CC(https://rust.cc/)，get lots of stars\n\n2020.03.01\nextract Ref from Oop, access prime value, no need lock anymore\nextract DataArea from Frame, printStackTrace has Line Number\nIncluded in 科技爱好者周刊 96th，thank yifeng\nhttp://www.ruanyifeng.com/blog/2020/02/weekly-issue-96.html\n\n2020.03.03\nmerge first patch from CertainLach, thanks!\n\n2020.03.04\nCertainLach translate README & comments to english\n\n2020.03.05\nSwitch to Oracle JDK\ngithub 300 commits\n\n2020.03.12\nsupport annotation\n\n2020.03.17\nextract class-parser crate\n\n2020.03.22\ngithub 400 commits\n\n2020.04.18\ngithub 500 commits\n'javap' nearly complete\nstudy how to impl java threads\nsignature parser\n  rewrite based nom\n  support generic\n\n2020.05.10\nthreads supported\nstudy gc\n\n2020.06.06\nsimple gc based Rust Arc\navoid lock when access Oop::Ref\n\n2020.06.20\nstudy linux 'perf' && optimize, and performance is\ngetting better and better\n\n2020.06.25\ngithub 600 commits\nimprove vm performance\n  . rm RwLock of Frame's DataArea\n  . replace Slot::Primitive(vec bytes) by Slot::I32..., avoid vec malloc\n  . use jvm_initIDs to cache filed's offset(java_io_FileOutputStream)\n  . reimpl Oop::Ref as Box ptr, avoid lock\n  . ConstantPoolCache for method & field offset\n  . Cargo.toml profile.release conf\n  . cache MethodSignature in Method\nMyCheckProp:\n#sum_t_list_add     = 5494      -> 1507\n#sum_t_map_get      = 123       -> 27\n#sum_t_map_put      = 8         -> 3\n#sum_t_parse_int    = 626       -> 159\n#sum_t_println      = 3059      -> 768\n#sum_t_int2integer  = 3201      -> 1255\n\n"
  },
  {
    "path": "tools/javap/Cargo.toml",
    "content": "[package]\nname = \"javap\"\nversion = \"0.2.1\"\nauthors = [\"Dou Chuan <1843657913@qq.com>\"]\nedition = \"2018\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\nclap = \"2.33.1\"\nclassfile = { path = \"../../crates/classfile\", version = \"0.1.0\" }\nclass-parser = { path = \"../../crates/class-parser\", version = \"0.1.0\" }\ntime = \"0.2.16\"\nenv_logger = \"0.7.1\"\nhandlebars = \"3.0.1\"\nlazy_static = \"1.4.0\"\nlog = \"0.4.0\"\nmd5 = \"0.7.0\"\nserde = \"1.0.0\"\nserde_derive = \"1.0.75\"\nserde_json = \"1.0.39\"\nzip = \"0.5.4\"\n"
  },
  {
    "path": "tools/javap/run.sh",
    "content": "export RUST_LOG=trace\n#export RUST_LOG=info\n#export RUST_LOG=warn\nexport RUST_BACKTRACE=full\n\n### version\n#cargo run -q -- --version\n\n### line number\n#cargo run -q -- --cp test -l AbstractGraphicObject\n#cargo run -q -- --cp test -l GraphicObject\n#cargo run -q -- --cp test -l HelloWorld\n#cargo run -q -- --cp test -l EnumMobile\n#cargo run -q -- --cp test -l Interface1\n#cargo run -q -- --cp test -l Hockey\n#cargo run -q -- --cp test -l WifeAndMother\n\n### disassemble\n#cargo run -q -- --cp test -c HelloWorld\n\n### disassemble & line number\n#cargo run -q -- --cp test -c -l HelloWorld\n#cargo run -q -- --cp test -c -l EnumMobile\n\n\n#cargo run -q -- --cp test --constants HelloWorld\n#cargo run -q -- --cp test --constants Hockey\n\n### access flags\n#echo \"default access flags\"\n#cargo run -q -- --cp test HelloWorld\n#echo \"public\"\n#cargo run -q -- --cp test --public HelloWorld\n#echo \"protected\"\n#cargo run -q -- --cp test --protected HelloWorld\n#echo \"private\"\n#cargo run -q -- --cp test --private HelloWorld\n\n### conflict args, error\n#cargo run -- --cp test --private --public HelloWorld\n\n### sysinfo\n#cargo run -q -- --cp test --sysinfo HelloWorld\n#cargo run -q -- --cp test/testng-6.8.21.jar --sysinfo org.testng.collections.Lists\n#cargo run -q -- --cp test HelloWorld\n\n### Print internal type signatures\n#cargo run -q -- --cp test -s  HelloWorld\n### exception\n#cargo run -q -- --cp test  Ex\n#cargo run -q -- --cp test -s Ex\n#cargo run -q -- --cp test -c Ex\n#cargo run -q -- --cp test -v Ex\n\n#cargo run -q -- --cp test -v HelloWorld\n#cargo run -q -- --cp test/testng-6.8.21.jar -v org.testng.xml.XmlUtils\n#cargo run -q -- --cp test/testng-6.8.21.jar -v org.testng.xml.XmlUtils\n#cargo run -q -- --cp test/testng-6.8.21.jar -v org.testng.TestNG\n\n### contains generic params\n#cargo run -q -- --cp test/testng-6.8.21.jar  -v org.testng.TestNG\n#cargo run -q -- --cp test/testng-6.8.21.jar  -s org.testng.TestNG\n#cargo run -q -- --cp test/testng-6.8.21.jar  -v org.testng.TestRunner\n#cargo run -q -- --cp test/testng-6.8.21.jar  -v org.testng.reporters.Files\n#cargo run -q -- --cp test/testng-6.8.21.jar  -v org.testng.collections.Maps\ncargo run -q -- --cp test  -v Generic1\n\n\n### test Not Found\n#cargo run -q -- --cp test/testng-6.8.21.jar  -v passed.png\n"
  },
  {
    "path": "tools/javap/src/cmd/disassemble.rs",
    "content": "use crate::cmd::Cmd;\nuse crate::misc::SysInfo;\nuse crate::sd::{\n    ClassInfoSerde, ClassVersionSerde, FieldInfoSerde, LineNumberSerde, MethodInfoSerde,\n    StackMapFrameSerde, StackMapTableSerde, SysInfoSerde,\n};\nuse crate::template;\nuse crate::trans::{self, AccessFlagHelper, SignatureTypeTranslator};\nuse clap::ArgMatches;\nuse classfile::flags as access_flags;\nuse classfile::ClassFile;\n\npub struct Disassemble {\n    show_access_flags: u16,\n\n    enable_verbose: bool,\n    enable_line_number: bool,\n    enable_code: bool,\n    enable_sys_info: bool,\n    enable_inner_signature: bool,\n}\n\nimpl Disassemble {\n    pub fn new(m: &ArgMatches) -> Option<Self> {\n        let show_access_flags = Self::build_show_access_flags(m);\n\n        let enable_verbose = m.is_present(\"verbose\");\n        let enable_line_number = enable_verbose || m.is_present(\"line_number\");\n        let enable_code = enable_verbose || m.is_present(\"disassemble\");\n        let enable_sys_info = enable_verbose || m.is_present(\"sysinfo\");\n        let enable_inner_signature = enable_verbose || m.is_present(\"signatures\");\n\n        Some(Self {\n            show_access_flags,\n\n            enable_verbose,\n            enable_line_number,\n            enable_code,\n            enable_sys_info,\n            enable_inner_signature,\n        })\n    }\n}\n\nimpl Cmd for Disassemble {\n    fn run(&self, si: &SysInfo, cf: ClassFile) {\n        self.do_render(si, cf);\n    }\n}\n\nimpl Disassemble {\n    fn do_render(&self, si: &SysInfo, cf: ClassFile) {\n        let reg = template::get_engine();\n\n        let sys_info = self.build_sys_info(si, &cf);\n        let version = ClassVersionSerde {\n            minor: cf.version.minor,\n            major: cf.version.major,\n        };\n        let flags = trans::class_access_flags_name(&cf);\n        let source_file = trans::class_source_file(&cf);\n        let class_head = self.build_class_define(&cf);\n        let fields = self.build_fields(&cf);\n        let methods = self.build_methods(&cf);\n        let cp = if self.enable_verbose {\n            trans::class_constant_pool(&cf)\n        } else {\n            vec![]\n        };\n        let inner_classes = trans::class_inner_classes(&cf);\n        let has_inner_classes = self.enable_verbose && !inner_classes.is_empty();\n        let signature = trans::class_signature_raw(&cf).unwrap_or(\"\".to_string());\n        let has_signature = self.enable_verbose && !signature.is_empty();\n\n        let data = ClassInfoSerde {\n            sys_info,\n            version,\n            flags,\n            source_file,\n            class_head,\n            fields,\n            methods,\n            cp,\n            inner_classes,\n            signature,\n\n            enable_verbose: self.enable_verbose,\n            enable_sys_info: self.enable_sys_info,\n            has_inner_classes,\n            has_signature,\n        };\n\n        println!(\"{}\", reg.render_template(template::CLASS, &data).unwrap());\n    }\n}\n\nimpl Disassemble {\n    fn build_show_access_flags(m: &ArgMatches) -> u16 {\n        let mut flags = 0;\n\n        if m.is_present(\"public\") {\n            flags = access_flags::ACC_PUBLIC;\n        }\n\n        if m.is_present(\"protected\") {\n            flags = access_flags::ACC_PROTECTED;\n        }\n\n        if m.is_present(\"private\") {\n            flags = access_flags::ACC_PRIVATE;\n        }\n\n        flags\n    }\n\n    fn build_class_define(&self, cf: &ClassFile) -> String {\n        let mut head_parts = vec![];\n\n        let class_flags = trans::class_access_flags(&cf);\n        let this_class = trans::class_this_class(&cf);\n        head_parts.push(class_flags);\n        head_parts.push(this_class.clone());\n\n        if cf.acc_flags.is_interface() {\n            if cf.interfaces.len() != 0 {\n                head_parts.push(\"extends\".to_string());\n\n                let parent_interfaces = trans::class_parent_interfaces(&cf).join(\", \");\n                head_parts.push(parent_interfaces);\n            }\n        } else if cf.acc_flags.is_enum() {\n            head_parts.push(\"extends\".to_string());\n\n            let super_class = {\n                let mut super_class = trans::class_super_class(&cf);\n                super_class.push_str(\"<\");\n                super_class.push_str(this_class.as_str());\n                super_class.push_str(\">\");\n\n                super_class\n            };\n\n            head_parts.push(super_class);\n        } else {\n            let class_signature = trans::class_signature(&cf);\n            //build from Signature Attribute\n            match class_signature {\n                Some(cs) => {\n                    assert_eq!(cs.len(), cf.interfaces.len() + 1); //1 means super Class\n                    let super_class = cs.get(0).unwrap();\n                    head_parts.push(\"extends\".to_string());\n                    head_parts.push(super_class.into_string());\n\n                    if cs.len() > 1 {\n                        head_parts.push(\"implements\".to_string());\n                        for it in &cs[1..] {\n                            head_parts.push(it.into_string());\n                        }\n                    }\n                }\n                None => {\n                    let super_class = trans::class_super_class(&cf);\n                    if super_class != \"java.lang.Object\" {\n                        head_parts.push(\"extends\".to_string());\n                        head_parts.push(super_class);\n                    }\n\n                    if cf.interfaces.len() != 0 {\n                        head_parts.push(\"implements\".to_string());\n\n                        let parent_interfaces = trans::class_parent_interfaces(&cf).join(\", \");\n                        head_parts.push(parent_interfaces);\n                    }\n                }\n            }\n        }\n\n        head_parts.join(\" \")\n    }\n\n    fn build_sys_info(&self, si: &SysInfo, cf: &ClassFile) -> SysInfoSerde {\n        if self.enable_sys_info {\n            let source_file = trans::class_source_file(&cf);\n            SysInfoSerde {\n                class_file: si.class_file.clone(),\n                last_modified: si.last_modified.clone(),\n                size: si.size,\n                checksum: si.checksum.clone(),\n                compiled_from: source_file,\n            }\n        } else {\n            SysInfoSerde::default()\n        }\n    }\n\n    fn build_fields(&self, cf: &ClassFile) -> Vec<FieldInfoSerde> {\n        let fields = trans::class_fields(&cf, self.show_access_flags);\n        fields\n            .iter()\n            .map(|it| FieldInfoSerde {\n                desc: it.desc.clone(),\n                descriptor: it.descriptor.clone(),\n                signature: it.signature.clone(),\n                flags: it.flags.clone(),\n                constant: it.constant.clone(),\n                enable_descriptor: self.enable_inner_signature,\n                enable_attr_signature: !it.signature.is_empty() && self.enable_verbose,\n                enable_flags: self.enable_verbose,\n                enable_constant: !it.constant.is_empty() && self.enable_verbose,\n            })\n            .collect()\n    }\n\n    fn build_methods(&self, cf: &ClassFile) -> Vec<MethodInfoSerde> {\n        let is_interface = cf.acc_flags.is_interface();\n\n        let methods = trans::class_methods(\n            cf,\n            self.enable_line_number,\n            self.enable_code,\n            self.show_access_flags,\n        );\n\n        methods\n            .iter()\n            .map(|it| {\n                if is_interface {\n                    MethodInfoSerde {\n                        desc: it.desc.clone(),\n                        line_number_table: vec![],\n                        code: Default::default(),\n                        descriptor: it.descriptor.clone(),\n                        signature: it.signature.clone(),\n                        flags: \"\".to_string(),\n                        throws: \"\".to_string(),\n                        ex_table: vec![],\n                        stack_map_table: Default::default(),\n                        local_var_table: vec![],\n                        local_var_type_table: vec![],\n\n                        enable_line_number: false,\n                        enable_code: false,\n                        enable_descriptor: self.enable_inner_signature,\n                        enable_flags: false,\n                        enable_throws: false,\n                        enable_stack_map: false,\n                        enable_local_var_table: false,\n                        enable_local_var_type_table: false,\n                        enable_attr_signature: false,\n\n                        has_ex_table: false,\n                    }\n                } else {\n                    let enable_line_number = self.enable_line_number;\n                    let enable_code = self.enable_code;\n\n                    let line_number_table: Vec<LineNumberSerde> = if enable_line_number {\n                        it.line_num_table\n                            .iter()\n                            .map(|it| LineNumberSerde {\n                                start_pc: it.start_pc,\n                                line_number: it.number,\n                            })\n                            .collect()\n                    } else {\n                        vec![]\n                    };\n\n                    let code = if enable_code {\n                        let mut code = it.code.clone();\n                        code.enable_verbose = self.enable_verbose;\n                        code\n                    } else {\n                        Default::default()\n                    };\n\n                    let stack_map_table = if self.enable_verbose {\n                        let frames: Vec<StackMapFrameSerde> = it\n                            .stack_map_table\n                            .iter()\n                            .map(|frame| {\n                                let desc = format!(\"frame_type = {} {}\", frame.tag, frame.comment);\n                                StackMapFrameSerde {\n                                    desc,\n                                    items: frame.items.clone(),\n                                }\n                            })\n                            .collect();\n                        StackMapTableSerde {\n                            number_of_entries: frames.len(),\n                            frames,\n                        }\n                    } else {\n                        Default::default()\n                    };\n                    let local_var_table = it.local_variable_table.clone();\n                    let local_var_type_table = it.local_variable_type_table.clone();\n                    let enable_stack_map =\n                        !stack_map_table.frames.is_empty() && self.enable_verbose;\n                    let enable_local_var_table = !local_var_table.is_empty()\n                        && (self.enable_verbose || self.enable_line_number);\n                    let enable_local_var_type_table =\n                        !local_var_type_table.is_empty() && self.enable_verbose;\n\n                    MethodInfoSerde {\n                        desc: it.desc.clone(),\n                        line_number_table,\n                        code,\n                        descriptor: it.descriptor.clone(),\n                        signature: it.signature.clone(),\n                        flags: it.flags.clone(),\n                        throws: it.throws.clone(),\n                        ex_table: it.ex_table.clone(),\n                        stack_map_table,\n                        local_var_table,\n                        local_var_type_table,\n\n                        enable_line_number,\n                        enable_code,\n                        enable_descriptor: self.enable_inner_signature,\n                        enable_flags: self.enable_verbose,\n                        enable_throws: !it.throws.is_empty() && self.enable_verbose,\n                        enable_stack_map,\n                        enable_local_var_table,\n                        enable_local_var_type_table,\n                        enable_attr_signature: !it.signature.is_empty() && self.enable_verbose,\n\n                        has_ex_table: !it.ex_table.is_empty() && enable_code,\n                    }\n                }\n            })\n            .collect()\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/cmd/mod.rs",
    "content": "use crate::misc::SysInfo;\nuse classfile::ClassFile;\n\nmod disassemble;\n\npub use disassemble::Disassemble;\n\npub trait Cmd {\n    fn run(&self, si: &SysInfo, cf: ClassFile);\n}\n"
  },
  {
    "path": "tools/javap/src/main.rs",
    "content": "#[macro_use]\nextern crate serde_derive;\n#[macro_use]\nextern crate serde_json;\nextern crate handlebars;\n#[macro_use]\nextern crate lazy_static;\n#[macro_use]\nextern crate log;\n\nextern crate clap;\nextern crate env_logger;\n\nmod cmd;\nmod misc;\nmod sd;\nmod strategy;\nmod template;\nmod trans;\nmod util;\n\nuse clap::{App, Arg};\nuse class_parser::parse_class;\n\n/*\nUsage: javap <options> <classes>\nwhere possible options include:\n  -help  --help  -?        Print this usage message\n  -version                 Version information\n  -v  -verbose             Print additional information\n  -l                       Print line number and local variable tables\n  -public                  Show only public classes and members\n  -protected               Show protected/public classes and members\n  -package                 Show package/protected/public classes\n                           and members (default)\n  -p  -private             Show all classes and members\n  -c                       Disassemble the code\n  -s                       Print internal type signatures\n  -sysinfo                 Show system info (path, size, date, MD5 hash)\n                           of class being processed\n  -constants               Show final constants\n  -classpath <path>        Specify where to find user class files\n  -cp <path>               Specify where to find user class files\n  -bootclasspath <path>    Override location of bootstrap class files\n\n*/\n\n/*\ntodo:\n    1. can clap support '-private' style option?\n\n    2. line_number::render_enum, Handlebars's render format looks ugly\n      custom control counts of spaces\n      try the other template engine\n*/\nfn main() {\n    init();\n\n    let matches = App::new(\"\")\n        .arg(\n            Arg::with_name(\"version\")\n                .long(\"version\")\n                .help(\"Print this usage message\"),\n        )\n        .arg(\n            Arg::with_name(\"verbose\")\n                .long(\"verbose\")\n                .short(\"v\")\n                .help(\"Print additional information\"),\n        )\n        .arg(\n            Arg::with_name(\"line_number\")\n                .short(\"l\")\n                .help(\"Print line number and local variable tables\"),\n        )\n        .arg(\n            Arg::with_name(\"public\")\n                .long(\"public\")\n                .conflicts_with_all(&[\"protected\", \"package\", \"private\"])\n                .help(\"Show only public classes and members\"),\n        )\n        .arg(\n            Arg::with_name(\"protected\")\n                .long(\"protected\")\n                .help(\"Show protected/public classes and members\"),\n        )\n        .arg(\n            Arg::with_name(\"package\")\n                .long(\"package\")\n                .help(\"Show package/protected/public classes\\nand members (default)\"),\n        )\n        .arg(\n            Arg::with_name(\"private\")\n                .long(\"private\")\n                .short(\"p\")\n                .help(\"Show all classes and members\"),\n        )\n        .arg(\n            Arg::with_name(\"disassemble\")\n                .short(\"c\")\n                .help(\"Disassemble the code\"),\n        )\n        .arg(\n            Arg::with_name(\"signatures\")\n                .short(\"s\")\n                .help(\"Print internal type signatures\"),\n        )\n        .arg(\n            Arg::with_name(\"sysinfo\")\n                .long(\"sysinfo\")\n                .help(\"Show system info (path, size, date, MD5 hash)\\nof class being processed\"),\n        )\n        .arg(\n            Arg::with_name(\"constants\")\n                .long(\"constants\")\n                .help(\"Show final constants\"),\n        )\n        .arg(\n            Arg::with_name(\"cp\")\n                .long(\"cp\")\n                .help(\"Specify where to find user class files\")\n                .default_value(\".\")\n                .takes_value(true),\n        )\n        .arg(\n            Arg::with_name(\"classpath\")\n                .long(\"classpath\")\n                .help(\"Specify where to find user class files\")\n                .default_value(\".\")\n                .takes_value(true),\n        )\n        .arg(Arg::with_name(\"classes\").multiple(true).index(1))\n        .get_matches();\n\n    strategy::setup_classpath(&matches);\n\n    if matches.is_present(\"version\") {\n        println!(env!(\"CARGO_PKG_VERSION\"));\n    }\n\n    let commander = strategy::choose(&matches);\n\n    match matches.values_of(\"classes\") {\n        Some(classes) => {\n            for it in classes {\n                match misc::find_class(it) {\n                    Ok(r) => {\n                        if let Ok((_, cf)) = parse_class(&r.1) {\n                            commander.run(&r.0, cf);\n                        } else {\n                            error!(\"parse class error: {}\", it);\n                        }\n                    }\n                    Err(_e) => {\n                        println!(\"Error: class not found: {}\", it);\n                    }\n                }\n            }\n        }\n        None => (),\n    }\n}\n\nfn init() {\n    env_logger::init();\n    misc::cp_manager_init();\n}\n"
  },
  {
    "path": "tools/javap/src/misc/class_path_manager.rs",
    "content": "#![allow(unused)]\n\nuse crate::misc::SysInfo;\nuse crate::util;\nuse std::fs::File;\nuse std::io::{self, Read};\nuse std::path::Path;\nuse std::sync::{Arc, Mutex};\nuse zip::ZipArchive;\n\nlazy_static! {\n    static ref CPM: Mutex<ClassPathManager> = { Mutex::new(ClassPathManager::new()) };\n}\n\npub fn init() {\n    lazy_static::initialize(&CPM);\n}\n\npub fn find_class(name: &str) -> Result<ClassPathResult, io::Error> {\n    let cpm = CPM.lock().unwrap();\n    cpm.search_class(name)\n}\n\npub fn add_path(path: &str) {\n    let mut cpm = CPM.lock().unwrap();\n    let _ = cpm.add_class_path(path);\n}\n\npub fn add_paths(path: &str) {\n    let mut cpm = CPM.lock().unwrap();\n    cpm.add_class_paths(path);\n}\n\n#[derive(Debug)]\n// pub struct ClassPathResult(pub SysInfo, pub Vec<u8>);\npub struct ClassPathResult(pub SysInfo, pub Vec<u8>);\n\ntype ZipRef = Arc<Mutex<Box<ZipArchive<File>>>>;\n\nenum ClassSource {\n    Dir(String),\n    Jar(ZipRef, String),\n}\n\nstruct ClassPathManager {\n    runtime_class_path: Vec<ClassSource>,\n}\n\nimpl ClassPathManager {\n    fn new() -> Self {\n        Self {\n            runtime_class_path: vec![],\n        }\n    }\n\n    pub fn add_class_path(&mut self, path: &str) -> Result<(), io::Error> {\n        let p = Path::new(path);\n        if p.is_dir() {\n            self.runtime_class_path\n                .push(ClassSource::Dir(path.to_string()));\n        } else {\n            let f = File::open(p)?;\n            let z = ZipArchive::new(f)?;\n            let handle = Arc::new(Mutex::new(Box::new(z)));\n            self.runtime_class_path\n                .push(ClassSource::Jar(handle, path.to_string()));\n        }\n\n        Ok(())\n    }\n\n    pub fn add_class_paths(&mut self, path: &str) {\n        path.split(util::PATH_SEP)\n            .for_each(|p| match self.add_class_path(p) {\n                Err(e) => error!(\"add class path error, path={}, e={:?}\", p, e),\n                _ => (),\n            });\n    }\n\n    pub fn search_class(&self, name: &str) -> Result<ClassPathResult, io::Error> {\n        let name = name.replace(\"/\", util::FILE_SEP);\n        let name = name.replace(\".\", util::FILE_SEP);\n\n        // trace!(\"search_class: {}\", name);\n\n        for it in self.runtime_class_path.iter() {\n            match it {\n                ClassSource::Dir(path) => {\n                    let mut p = String::from(path);\n                    p.push_str(util::FILE_SEP);\n                    p.push_str(&name);\n                    p.push_str(\".class\");\n                    match File::open(&p) {\n                        Ok(mut f) => {\n                            //todo: process error\n                            let meta = f.metadata().unwrap();\n                            let mut v = Vec::with_capacity(meta.len() as usize);\n                            let _ = f.read_to_end(&mut v);\n\n                            let sys_info = SysInfo {\n                                class_file: util::to_abs_path(&p),\n                                last_modified: util::format_time1(meta.modified().unwrap()),\n                                size: meta.len() as usize,\n                                checksum: util::md5_checksum(v.as_slice()),\n                            };\n\n                            return Ok(ClassPathResult(sys_info, v));\n                        }\n\n                        _ => (),\n                    }\n                }\n\n                ClassSource::Jar(handle, path) => {\n                    let mut p = String::from(&name);\n                    p.push_str(\".class\");\n\n                    let mut handle = handle.lock().unwrap();\n                    let zf = handle.by_name(&p);\n\n                    match zf {\n                        Ok(mut zf) => {\n                            let mut v = Vec::with_capacity(zf.size() as usize);\n                            let r = zf.read_to_end(&mut v);\n                            assert!(r.is_ok());\n\n                            let mut class_file = String::from(util::JAR_FILE_PREFIX);\n                            let jar_abs = util::to_abs_path(path);\n                            class_file.push_str(jar_abs.as_str());\n                            class_file.push_str(\"!/\");\n                            class_file.push_str(p.as_str());\n\n                            let t = zf.last_modified().to_time().to_timespec().sec;\n                            let sys_info = SysInfo {\n                                class_file,\n                                last_modified: util::format_time2(t),\n                                size: zf.size() as usize,\n                                checksum: util::md5_checksum(v.as_slice()),\n                            };\n\n                            return Ok(ClassPathResult(sys_info, v));\n                        }\n\n                        _ => (),\n                    }\n                }\n            }\n        }\n\n        return Err(io::Error::new(\n            io::ErrorKind::NotFound,\n            format!(\"Search class failed: {}\", name),\n        ));\n    }\n\n    pub fn size(&self) -> usize {\n        self.runtime_class_path.len()\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/misc/mod.rs",
    "content": "mod class_path_manager;\nmod sys_info;\n\npub use class_path_manager::add_path as add_cp_path;\npub use class_path_manager::find_class;\npub use class_path_manager::init as cp_manager_init;\npub use sys_info::SysInfo;\n"
  },
  {
    "path": "tools/javap/src/misc/sys_info.rs",
    "content": "#[derive(Debug, Clone)]\npub struct SysInfo {\n    pub class_file: String,\n    pub last_modified: String,\n    pub size: usize,\n    pub checksum: String,\n}\n"
  },
  {
    "path": "tools/javap/src/sd/mod.rs",
    "content": "#[derive(Serialize)]\npub struct ClassInfoSerde {\n    pub sys_info: SysInfoSerde,\n    pub version: ClassVersionSerde,\n    pub flags: String,\n    pub source_file: String,\n    pub class_head: String,\n    pub fields: Vec<FieldInfoSerde>,\n    pub methods: Vec<MethodInfoSerde>,\n    pub cp: Vec<String>,\n    pub inner_classes: Vec<String>,\n    pub signature: String,\n\n    pub enable_verbose: bool,\n    pub enable_sys_info: bool,\n\n    pub has_inner_classes: bool,\n    pub has_signature: bool,\n}\n\n#[derive(Serialize)]\npub struct MethodInfoSerde {\n    pub desc: String,\n\n    pub line_number_table: Vec<LineNumberSerde>,\n    pub descriptor: String,\n    pub signature: String,\n    pub code: CodeSerde,\n    pub flags: String,\n    pub throws: String,\n    pub ex_table: Vec<String>,\n    pub stack_map_table: StackMapTableSerde,\n    pub local_var_table: Vec<String>,\n    pub local_var_type_table: Vec<String>,\n\n    pub enable_line_number: bool,\n    pub enable_code: bool,\n    pub enable_descriptor: bool,\n    pub enable_flags: bool,\n    pub enable_throws: bool,\n    pub enable_stack_map: bool,\n    pub enable_local_var_table: bool,\n    pub enable_local_var_type_table: bool,\n    pub enable_attr_signature: bool,\n\n    pub has_ex_table: bool,\n}\n\n#[derive(Serialize, Clone)]\npub struct CodeSerde {\n    pub max_stack: u16,\n    pub max_locals: u16,\n    pub args_size: usize,\n    pub codes: Vec<String>,\n\n    pub enable_verbose: bool,\n}\n\n#[derive(Serialize)]\npub struct FieldInfoSerde {\n    pub desc: String,\n\n    pub descriptor: String, //constant pool descriptor\n    pub signature: String,  //Attribute Signature\n    pub flags: String,\n    pub constant: String,\n\n    pub enable_descriptor: bool,\n    pub enable_flags: bool,\n    pub enable_attr_signature: bool,\n    pub enable_constant: bool,\n}\n\n#[derive(Serialize)]\npub struct LineNumberSerde {\n    pub start_pc: u16,\n    pub line_number: u16,\n}\n\n#[derive(Serialize)]\npub struct SysInfoSerde {\n    pub class_file: String,\n    pub last_modified: String,\n    pub size: usize,\n    pub checksum: String,\n    pub compiled_from: String,\n}\n\n#[derive(Serialize)]\npub struct ClassVersionSerde {\n    pub minor: u16,\n    pub major: u16,\n}\n\n#[derive(Serialize)]\npub struct StackMapTableSerde {\n    pub number_of_entries: usize,\n    pub frames: Vec<StackMapFrameSerde>,\n}\n\n#[derive(Serialize)]\npub struct StackMapFrameSerde {\n    pub desc: String,\n    pub items: Vec<String>,\n}\n\nimpl Default for SysInfoSerde {\n    fn default() -> Self {\n        Self {\n            class_file: \"\".to_string(),\n            last_modified: \"\".to_string(),\n            size: 0,\n            checksum: \"\".to_string(),\n            compiled_from: \"\".to_string(),\n        }\n    }\n}\n\nimpl Default for CodeSerde {\n    fn default() -> Self {\n        Self {\n            max_stack: 0,\n            max_locals: 0,\n            args_size: 0,\n            codes: vec![],\n\n            enable_verbose: false,\n        }\n    }\n}\n\nimpl Default for StackMapTableSerde {\n    fn default() -> Self {\n        Self {\n            number_of_entries: 0,\n            frames: vec![],\n        }\n    }\n}\n\nimpl Default for StackMapFrameSerde {\n    fn default() -> Self {\n        Self {\n            desc: \"\".to_string(),\n            items: vec![],\n        }\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/strategy.rs",
    "content": "use crate::cmd::{Cmd, Disassemble};\nuse crate::misc;\nuse crate::util;\nuse clap::ArgMatches;\n\npub fn choose(m: &ArgMatches) -> Box<dyn Cmd> {\n    match Disassemble::new(m) {\n        Some(d) => Box::new(d),\n        None => unimplemented!(),\n    }\n}\n\npub fn setup_classpath(matches: &ArgMatches) {\n    let mut added = std::collections::HashSet::new();\n\n    vec![\n        matches.value_of(\"cp\").unwrap(),\n        matches.value_of(\"classpath\").unwrap(),\n    ]\n    .iter()\n    .for_each(|&v| {\n        let paths = v.split(util::PATH_SEP);\n        paths.for_each(|path| {\n            if !added.contains(path) {\n                misc::add_cp_path(path);\n                added.insert(path);\n            }\n        });\n    });\n}\n"
  },
  {
    "path": "tools/javap/src/template.rs",
    "content": "use handlebars::Handlebars;\n\npub const PART_COMPILED_FROM: &str = \"Compiled from \\\"{{source_file}}\\\"\";\npub const PART_SYS_INFO: &str = \"\nClassfile {{sys_info.class_file}}\n  Last modified {{sys_info.last_modified}}; size {{sys_info.size}} bytes\n  MD5 checksum {{sys_info.checksum}}\n  Compiled from \\\"{{sys_info.compiled_from}}\\\"\";\n\npub const PART_FIELDS: &str = \"\n{{~#each fields as |field|}}\n  {{ desc }}\n  {{~#if enable_descriptor}}\n    descriptor: {{descriptor~}}\n  {{/if}}\n  {{~#if enable_flags}}\n    flags: {{flags~}}\n  {{/if}}\n  {{~#if enable_attr_signature}}\n    Signature: {{signature~}}\n  {{/if}}\n  {{~#if enable_constant}}\n    ConstantValue: {{constant~}}\n  {{/if}}\n{{/each}}\";\n\npub const PART_METHODS: &str = \"\n{{~#each methods}}\n  {{ desc }}\n  {{~#if enable_descriptor}}\n    descriptor: {{descriptor~}}\n  {{/if}}\n  {{~#if enable_flags}}\n    flags: {{flags~}}\n  {{/if}}\n  {{~#if enable_code}}\n    Code:\n    {{~#if code.enable_verbose}}\n      stack={{code.max_stack}}, locals={{code.max_locals}}, args_size={{code.args_size~}}\n    {{/if}}\n    {{~#each code.codes}}\n      {{this ~}}\n    {{/each~}}\n  {{/if}}\n  {{~#if has_ex_table}}\n    Exception table:\n    {{~#each ex_table}}\n      {{this ~}}\n    {{/each}}\n  {{/if}}\n  {{~#if enable_line_number}}\n    LineNumberTable:\n      {{~#each line_number_table}}\n        line {{line_number}}: {{start_pc ~}}\n      {{/each~}}\n  {{/if}}\n  {{~#if enable_local_var_table}}\n    LocalVariableTable:\n      {{~#each local_var_table}}\n        {{this ~}}\n      {{/each~}}\n  {{/if}}\n  {{~#if enable_local_var_type_table}}\n    LocalVariableTypeTable:\n      {{~#each local_var_type_table}}\n        {{this ~}}\n      {{/each~}}\n  {{/if}}\n  {{~#if enable_stack_map}}\n    StackMapTable: number_of_entries = {{stack_map_table.number_of_entries}}\n      {{~#each stack_map_table.frames}}\n        {{desc}}\n        {{~#each items}}\n          {{this ~}}\n        {{/each~}}\n      {{/each~}}\n  {{/if}}\n  {{~#if enable_throws}}\n    Exceptions:\n      throws {{throws}}\n  {{/if}}\n  {{~#if enable_attr_signature}}\n    Signature: {{signature}}\n  {{/if}}\n{{/each}}\";\n\npub const PART_CP: &str = \"\nConstant pool:\n{{~#each cp}}\n{{this ~}}\n{{/each}}\n\";\n\npub const CLASS: &str = \"\n{{~#if enable_sys_info}}\n{{~> sys_info ~}}\n{{~else~}}\n{{~> compiled_from}}\n{{/if}}\n{{~#if enable_verbose }}\n{{class_head}}\n  minor version: {{version.minor}}\n  major version: {{version.major}}\n  flags: {{flags}}\n{{~> constant_pool ~}}\n{\n{{~else~}}\n{{class_head}} {\n{{/if}}\n  {{~> fields }}\n  {{~> methods }}\n}\n{{~#if has_signature}}\n{{signature~}}\n{{/if}}\n{{~#if enable_verbose}}\nSourceFile: \\\"{{source_file}}\\\"\n{{~/if~}}\n{{~#if has_inner_classes}}\nInnerClasses:\n{{~#each inner_classes}}\n    {{this ~}}\n{{/each}}\n{{/if}}\n\";\n\npub fn get_engine() -> Handlebars<'static> {\n    let mut h = Handlebars::new();\n    let _ = h.register_partial(\"compiled_from\", PART_COMPILED_FROM);\n    let _ = h.register_partial(\"sys_info\", PART_SYS_INFO);\n    let _ = h.register_partial(\"fields\", PART_FIELDS);\n    let _ = h.register_partial(\"methods\", PART_METHODS);\n    let _ = h.register_partial(\"constant_pool\", PART_CP);\n    // let _ = h.register_partial(\"stack_map_table\", PART_STACK_MAP_TABLE);\n    h.register_escape_fn(handlebars::no_escape);\n\n    h\n}\n"
  },
  {
    "path": "tools/javap/src/trans/access_flag.rs",
    "content": "use classfile::flags as class_flags;\n\npub struct Translator {\n    flags: AccessFlag,\n}\n\nimpl Translator {\n    pub fn new(flags: AccessFlag) -> Self {\n        Self { flags }\n    }\n}\n\nimpl Translator {\n    pub fn class_access_flags(&self, only_flag: bool) -> String {\n        let mut parts = vec![];\n        let flags = self.flags;\n\n        if flags.is_public() {\n            parts.push(\"public\");\n        }\n\n        if flags.is_static() {\n            parts.push(\"static\");\n        }\n\n        if flags.is_final() {\n            parts.push(\"final\");\n        }\n\n        if !only_flag {\n            if flags.is_interface() {\n                parts.push(\"interface\");\n            } else if flags.is_enum() {\n                parts.push(\"class\");\n            } else {\n                if flags.is_abstract() {\n                    parts.push(\"abstract class\");\n                } else {\n                    parts.push(\"class\")\n                }\n            }\n        }\n\n        parts.join(\" \")\n    }\n\n    pub fn method_access_flags(&self) -> String {\n        let mut parts = vec![];\n        let flags = self.flags;\n\n        if flags.is_public() {\n            parts.push(\"public\");\n        } else if flags.is_protected() {\n            parts.push(\"protected\");\n        } else if flags.is_private() {\n            parts.push(\"private\");\n        }\n\n        if flags.is_static() {\n            parts.push(\"static\");\n        }\n\n        if flags.is_native() {\n            parts.push(\"native\");\n        }\n\n        if flags.is_final() {\n            parts.push(\"final\");\n        } else if flags.is_abstract() {\n            parts.push(\"abstract\");\n        }\n\n        parts.join(\" \")\n    }\n\n    pub fn field_access_flags(&self) -> String {\n        let mut parts = vec![];\n        let flags = self.flags;\n\n        if flags.is_public() {\n            parts.push(\"public\");\n        } else if flags.is_protected() {\n            parts.push(\"protected\");\n        } else if flags.is_private() {\n            parts.push(\"private\");\n        }\n\n        if flags.is_static() {\n            parts.push(\"static\");\n        }\n\n        if flags.is_final() {\n            parts.push(\"final\");\n        }\n\n        parts.join(\" \")\n    }\n\n    pub fn access_flag_inner(&self) -> String {\n        let mut parts = vec![];\n        let flags = self.flags;\n\n        if flags.is_public() {\n            parts.push(\"ACC_PUBLIC\");\n        }\n\n        if flags.is_protected() {\n            parts.push(\"ACC_PROTECTED\");\n        }\n\n        if flags.is_static() {\n            parts.push(\"ACC_STATIC\");\n        }\n\n        if flags.is_final() {\n            parts.push(\"ACC_FINAL\");\n        }\n\n        if flags.is_super() {\n            parts.push(\"ACC_SUPER\");\n        }\n\n        if flags.is_interface() {\n            parts.push(\"ACC_INTERFACE\");\n        }\n\n        if flags.is_abstract() {\n            parts.push(\"ACC_ABSTRACT\");\n        }\n\n        if flags.is_annotation() {\n            parts.push(\"ACC_ANNOTATION\");\n        }\n\n        if flags.is_enum() {\n            parts.push(\"ACC_ENUM\");\n        }\n\n        parts.join(\", \")\n    }\n}\n\ntype AccessFlag = u16;\n\npub trait AccessFlagHelper {\n    fn is_public(&self) -> bool;\n    fn is_final(&self) -> bool;\n    fn is_super(&self) -> bool;\n    fn is_interface(&self) -> bool;\n    fn is_abstract(&self) -> bool;\n    fn is_synthetic(&self) -> bool;\n    fn is_annotation(&self) -> bool;\n    fn is_enum(&self) -> bool;\n    fn is_private(&self) -> bool;\n    fn is_protected(&self) -> bool;\n    fn is_static(&self) -> bool;\n    fn is_synchronized(&self) -> bool;\n    fn is_bridge(&self) -> bool;\n    fn is_varargs(&self) -> bool;\n    fn is_native(&self) -> bool;\n    fn is_strict(&self) -> bool;\n    fn is_package(&self) -> bool;\n    fn compare(&self, other: u16) -> i32;\n}\n\nimpl AccessFlagHelper for AccessFlag {\n    fn is_public(&self) -> bool {\n        (*self & class_flags::ACC_PUBLIC) != 0\n    }\n\n    fn is_final(&self) -> bool {\n        (*self & class_flags::ACC_FINAL) != 0\n    }\n\n    fn is_super(&self) -> bool {\n        (*self & class_flags::ACC_SUPER) != 0\n    }\n\n    fn is_interface(&self) -> bool {\n        (*self & class_flags::ACC_INTERFACE) != 0\n    }\n\n    fn is_abstract(&self) -> bool {\n        (*self & class_flags::ACC_ABSTRACT) != 0\n    }\n\n    fn is_synthetic(&self) -> bool {\n        (*self & class_flags::ACC_SYNTHETIC) != 0\n    }\n\n    fn is_annotation(&self) -> bool {\n        (*self & class_flags::ACC_ANNOTATION) != 0\n    }\n\n    fn is_enum(&self) -> bool {\n        (*self & class_flags::ACC_ENUM) != 0\n    }\n\n    fn is_private(&self) -> bool {\n        (*self & class_flags::ACC_PRIVATE) != 0\n    }\n\n    fn is_protected(&self) -> bool {\n        (*self & class_flags::ACC_PROTECTED) != 0\n    }\n\n    fn is_static(&self) -> bool {\n        (*self & class_flags::ACC_STATIC) != 0\n    }\n\n    fn is_synchronized(&self) -> bool {\n        (*self & class_flags::ACC_SYNCHRONIZED) != 0\n    }\n\n    fn is_bridge(&self) -> bool {\n        (*self & class_flags::ACC_BRIDGE) != 0\n    }\n\n    fn is_varargs(&self) -> bool {\n        (*self & class_flags::ACC_VARARGS) != 0\n    }\n\n    fn is_native(&self) -> bool {\n        (*self & class_flags::ACC_NATIVE) != 0\n    }\n\n    fn is_strict(&self) -> bool {\n        (*self & class_flags::ACC_STRICT) != 0\n    }\n\n    fn is_package(&self) -> bool {\n        *self == 0\n    }\n\n    //compare access permission\n    //  *self >  other,  1\n    //  *self == other,  0\n    //  *self <  other, -1\n    fn compare(&self, other: u16) -> i32 {\n        let flags = *self;\n        if flags == other {\n            return 0;\n        }\n\n        if flags == 0 {\n            if other.is_private() {\n                return 1;\n            }\n        } else if flags.is_public() {\n            if !other.is_public() {\n                return 1;\n            }\n        } else if flags.is_protected() {\n            if other == 0 || other.is_private() {\n                return 1;\n            }\n        }\n\n        -1\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/class_file.rs",
    "content": "use super::FieldTranslator;\nuse super::{MethodTranslation, MethodTranslator};\nuse crate::trans::AccessFlagsTranslator;\nuse crate::trans::{AccessFlagHelper, FieldTranslation};\nuse class_parser::ClassSignature;\nuse classfile::AttributeType;\nuse classfile::ClassFile;\nuse classfile::{constant_pool, SignatureType};\n\nconst S_UNKNOWN: &str = \"unknown\";\n\npub struct Translator<'a> {\n    cf: &'a ClassFile,\n}\n\nimpl<'a> Translator<'a> {\n    pub fn new(cf: &'a ClassFile) -> Self {\n        Self { cf }\n    }\n}\n\nimpl<'a> Translator<'a> {\n    pub fn source_file(&self) -> String {\n        for it in &self.cf.attrs {\n            match it {\n                AttributeType::SourceFile { source_file_index } => {\n                    return constant_pool::get_utf8(&self.cf.cp, *source_file_index as usize)\n                        .map_or_else(\n                            || S_UNKNOWN.into(),\n                            |v| String::from_utf8_lossy(v.as_slice()).into(),\n                        );\n                }\n                _ => (),\n            }\n        }\n\n        String::from(S_UNKNOWN)\n    }\n\n    pub fn this_class(&self) -> String {\n        constant_pool::get_class_name(&self.cf.cp, self.cf.this_class as usize).map_or_else(\n            || S_UNKNOWN.into(),\n            |v| String::from_utf8_lossy(v.as_slice()).replace(\"/\", \".\"),\n        )\n    }\n\n    pub fn super_class(&self) -> String {\n        constant_pool::get_class_name(&self.cf.cp, self.cf.super_class as usize).map_or_else(\n            || S_UNKNOWN.into(),\n            |v| String::from_utf8_lossy(v.as_slice()).replace(\"/\", \".\"),\n        )\n    }\n\n    pub fn parent_interfaces(&self) -> Vec<String> {\n        assert_ne!(self.cf.interfaces.len(), 0);\n        let mut interfaces = Vec::with_capacity(self.cf.interfaces.len());\n\n        for it in self.cf.interfaces.iter() {\n            let name = constant_pool::get_class_name(&self.cf.cp, *it as usize).map_or_else(\n                || S_UNKNOWN.into(),\n                |v| String::from_utf8_lossy(v.as_slice()).replace(\"/\", \".\"),\n            );\n            interfaces.push(name);\n        }\n\n        interfaces\n    }\n\n    pub fn access_flags(&self) -> String {\n        let flags = self.cf.acc_flags;\n        let t = AccessFlagsTranslator::new(flags);\n        t.class_access_flags(false)\n    }\n\n    pub fn access_flags_name(&self) -> String {\n        let flags = self.cf.acc_flags;\n        let t = AccessFlagsTranslator::new(flags);\n        t.access_flag_inner()\n    }\n\n    pub fn signature_raw(&self) -> Option<String> {\n        self.cf.signature().map(|idx| {\n            let v = constant_pool::get_utf8(&self.cf.cp, idx).unwrap();\n            let signature = String::from_utf8_lossy(v.as_slice());\n            format!(\"Signature: #{:<28} // {}\", idx, signature)\n        })\n    }\n\n    pub fn signature(&self) -> Option<Vec<SignatureType>> {\n        self.cf.signature().map(|idx| {\n            let v = constant_pool::get_utf8(&self.cf.cp, idx).unwrap();\n            let v = ClassSignature::new(v.as_slice());\n            v.items.clone()\n        })\n    }\n\n    /*\n    desc = public HelloWorld();, acc_flags = 1\n    desc = public static void main(java.lang.String[]);, acc_flags = 9\n    desc = private void private_method();, acc_flags = 2\n    desc = protected void protected_method();, acc_flags = 4\n    desc = void package_method();, acc_flags = 0\n    desc = public void public_method();, acc_flags = 1\n    */\n    pub fn methods(\n        &self,\n        with_line_num: bool,\n        with_code: bool,\n        flags: u16,\n    ) -> Vec<MethodTranslation> {\n        let mut methods = Vec::with_capacity(self.cf.methods.len());\n        for it in self.cf.methods.iter() {\n            if it.acc_flags.is_bridge() {\n                continue;\n            }\n\n            if flags.compare(it.acc_flags) > 0 {\n                continue;\n            }\n\n            let t = MethodTranslator::new(self.cf, it);\n            methods.push(t.get(with_line_num, with_code));\n        }\n\n        methods\n    }\n\n    pub fn fields(&self, flags: u16) -> Vec<FieldTranslation> {\n        let mut fields = Vec::with_capacity(self.cf.fields.len());\n        for it in self.cf.fields.iter() {\n            let t = FieldTranslator::new(self.cf, it);\n\n            if it.acc_flags.is_synthetic() {\n                continue;\n            }\n\n            if flags.compare(it.acc_flags) > 0 {\n                continue;\n            }\n\n            fields.push(t.get());\n        }\n\n        fields\n    }\n\n    pub fn inner_classes(&self) -> Vec<String> {\n        let mut r = vec![];\n        match self.cf.inner_classes() {\n            Some(inners) => {\n                for it in inners.iter() {\n                    let inner_class_info_index = it.inner_class_info_index;\n                    let outer_class_info_index = it.outer_class_info_index;\n                    let inner_name_index = it.inner_name_index;\n                    let inner_class_access_flags = it.inner_class_access_flags;\n                    let flags = AccessFlagsTranslator::new(inner_class_access_flags);\n\n                    //top-level class or interface\n                    if outer_class_info_index == 0 {\n                        let inner_class_info = constant_pool::get_class_name(\n                            &self.cf.cp,\n                            inner_class_info_index as usize,\n                        )\n                        .unwrap();\n                        let v = format!(\n                            \"#{}; //class {}\",\n                            inner_class_info_index,\n                            String::from_utf8_lossy(inner_class_info.as_slice())\n                        );\n                        r.push(v);\n                    } else {\n                        if inner_class_access_flags.is_public() {\n                            let inner_class_info = constant_pool::get_class_name(\n                                &self.cf.cp,\n                                inner_class_info_index as usize,\n                            )\n                            .unwrap();\n                            let inner_class_info =\n                                String::from_utf8_lossy(inner_class_info.as_slice());\n                            let inner_name =\n                                constant_pool::get_utf8(&self.cf.cp, inner_name_index as usize)\n                                    .unwrap();\n                            let inner_name = String::from_utf8_lossy(inner_name.as_slice());\n                            let outer_class_info = constant_pool::get_class_name(\n                                &self.cf.cp,\n                                outer_class_info_index as usize,\n                            )\n                            .unwrap();\n                            let outer_class_info =\n                                String::from_utf8_lossy(outer_class_info.as_slice());\n                            let flags = flags.class_access_flags(true);\n                            let v = format!(\n                                \"{} #{}= #{} of #{}; //{}=class {} of class {}\",\n                                flags,\n                                inner_name_index,\n                                inner_class_info_index,\n                                outer_class_info_index,\n                                inner_name,\n                                inner_class_info,\n                                outer_class_info\n                            );\n                            r.push(v);\n                        }\n                    }\n                }\n            }\n            None => (),\n        }\n        r\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/code.rs",
    "content": "use super::instruction::{get_instructions, InstructionInfo};\nuse classfile::{attributes::Code, ClassFile, OpCode};\n\npub struct Translator<'a> {\n    pub cf: &'a ClassFile,\n    pub code: &'a Code,\n}\n\nimpl<'a> Translator<'a> {\n    pub fn get(&self) -> Vec<String> {\n        let codes = self.code.code.as_slice();\n        let infos = self.interp();\n        infos\n            .iter()\n            .map(|it| it.assemble(codes, &self.cf.cp))\n            .collect()\n    }\n}\n\nimpl<'a> Translator<'a> {\n    fn interp(&self) -> Vec<InstructionInfo> {\n        let mut infos = vec![];\n\n        let mut instructions = get_instructions();\n        let codes = self.code.code.as_slice();\n        let codes_len = codes.len();\n        let mut pc = 0;\n        let mut enable_wide = false;\n        loop {\n            if pc >= codes_len {\n                break;\n            }\n\n            let instruction = instructions.get_mut(codes[pc] as usize).unwrap();\n\n            if enable_wide {\n                instruction.set_wide(true);\n            }\n\n            let (info, new_pc) = instruction.run(codes, pc);\n\n            if enable_wide {\n                instruction.set_wide(false);\n                enable_wide = false;\n            }\n\n            if info.op_code == OpCode::wide {\n                enable_wide = true;\n            }\n\n            pc = new_pc;\n            infos.push(info);\n        }\n\n        infos\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/constant_pool_trans.rs",
    "content": "use classfile::constant_pool::{self, Type};\nuse classfile::{ClassFile, ConstantPoolType};\n\npub struct Translator<'a> {\n    pub cf: &'a ClassFile,\n}\n\nimpl<'a> Translator<'a> {\n    pub fn get(&self) -> Vec<String> {\n        let mut pool = Vec::with_capacity(self.cf.cp.len());\n\n        for (cp_idx, it) in self.cf.cp.iter().enumerate() {\n            let pos = format!(\"#{}\", cp_idx);\n\n            match it {\n                ConstantPoolType::Nop => (),\n                Type::Class { name_index } => {\n                    let index = format!(\"#{}\", *name_index);\n                    let name = constant_pool::get_utf8(&self.cf.cp, *name_index as usize).unwrap();\n                    let v = format!(\n                        \"{:>6} = {:18} {:14} // {}\",\n                        pos,\n                        \"Class\",\n                        index,\n                        String::from_utf8_lossy(name.as_slice())\n                    );\n                    pool.push(v);\n                }\n                Type::FieldRef {\n                    class_index,\n                    name_and_type_index,\n                } => {\n                    let index = format!(\"#{}.#{}\", *class_index, *name_and_type_index);\n                    let class_name =\n                        constant_pool::get_class_name(&self.cf.cp, *class_index as usize).unwrap();\n                    let (name, desc) = constant_pool::get_name_and_type(\n                        &self.cf.cp,\n                        *name_and_type_index as usize,\n                    );\n                    let name = name.unwrap();\n                    let desc = desc.unwrap();\n\n                    let class_name = String::from_utf8_lossy(class_name.as_slice());\n                    let name = String::from_utf8_lossy(name.as_slice());\n                    let desc = String::from_utf8_lossy(desc.as_slice());\n\n                    let v = format!(\n                        \"{:>6} = {:18} {:14} // {}.{}:{}\",\n                        pos, \"Fieldref\", index, class_name, name, desc\n                    );\n\n                    pool.push(v);\n                }\n                Type::MethodRef {\n                    class_index,\n                    name_and_type_index,\n                } => {\n                    let index = format!(\"#{}.#{}\", *class_index, *name_and_type_index);\n                    let class_name =\n                        constant_pool::get_class_name(&self.cf.cp, *class_index as usize).unwrap();\n                    let (name, desc) = constant_pool::get_name_and_type(\n                        &self.cf.cp,\n                        *name_and_type_index as usize,\n                    );\n                    let name = name.unwrap();\n                    let desc = desc.unwrap();\n\n                    let class_name = String::from_utf8_lossy(class_name.as_slice());\n                    let name = String::from_utf8_lossy(name.as_slice());\n                    let desc = String::from_utf8_lossy(desc.as_slice());\n                    let v = if name.as_bytes() == b\"<init>\" {\n                        format!(\n                            \"{:>6} = {:18} {:14} // {}.\\\"<init>\\\":{}\",\n                            pos, \"Methodref\", index, class_name, desc\n                        )\n                    } else {\n                        format!(\n                            \"{:>6} = {:18} {:14} // {}.{}:{}\",\n                            pos, \"Methodref\", index, class_name, name, desc\n                        )\n                    };\n\n                    pool.push(v);\n                }\n                Type::InterfaceMethodRef {\n                    class_index,\n                    name_and_type_index,\n                } => {\n                    let index = format!(\"#{}.#{}\", *class_index, *name_and_type_index);\n                    let class_name =\n                        constant_pool::get_class_name(&self.cf.cp, *class_index as usize).unwrap();\n                    let (name, desc) = constant_pool::get_name_and_type(\n                        &self.cf.cp,\n                        *name_and_type_index as usize,\n                    );\n                    let name = name.unwrap();\n                    let desc = desc.unwrap();\n\n                    let class_name = String::from_utf8_lossy(class_name.as_slice());\n                    let name = String::from_utf8_lossy(name.as_slice());\n                    let desc = String::from_utf8_lossy(desc.as_slice());\n                    let v = format!(\n                        \"{:>6} = {:18} {:14} // {}.{}:{}\",\n                        pos, \"InterfaceMethodref\", index, class_name, name, desc\n                    );\n\n                    pool.push(v);\n                }\n                Type::String { string_index } => {\n                    let index = format!(\"#{}\", *string_index);\n                    let constant_val = constant_pool::get_string(&self.cf.cp, cp_idx).unwrap();\n                    let v = format!(\n                        \"{:>6} = {:18} {:14} // {}\",\n                        pos,\n                        \"String\",\n                        index,\n                        constant_val.escape_default()\n                    );\n\n                    pool.push(v);\n                }\n                Type::Integer { v } => {\n                    let value = i32::from_be_bytes([v[0], v[1], v[2], v[3]]);\n                    let v = format!(\"{:>6} = {:18} {}\", pos, \"Int\", value);\n\n                    pool.push(v);\n                }\n                Type::Float { v } => {\n                    let value = u32::from_be_bytes([v[0], v[1], v[2], v[3]]);\n                    let value = f32::from_bits(value);\n                    let v = format!(\"{:>6} = {:18} {}f\", pos, \"Float\", value);\n\n                    pool.push(v);\n                }\n                Type::Long { v } => {\n                    let value =\n                        i64::from_be_bytes([v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]]);\n                    let v = format!(\"{:>6} = {:18} {}l\", pos, \"Long\", value,);\n\n                    pool.push(v);\n                }\n                Type::Double { v } => {\n                    let value =\n                        u64::from_be_bytes([v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]]);\n                    let value = f64::from_bits(value);\n\n                    let v = format!(\"{:>6} = {:18} {}d\", pos, \"Double\", value,);\n\n                    pool.push(v);\n                }\n                Type::NameAndType {\n                    name_index,\n                    desc_index,\n                } => {\n                    let index = format!(\"#{}.#{}\", *name_index, *desc_index);\n                    let name = constant_pool::get_utf8(&self.cf.cp, *name_index as usize).unwrap();\n                    let is_ctor = name.as_slice() == b\"<init>\";\n                    let name = String::from_utf8_lossy(name.as_ref());\n                    let desc = constant_pool::get_utf8(&self.cf.cp, *desc_index as usize).unwrap();\n                    let desc = String::from_utf8_lossy(desc.as_ref());\n\n                    let v = if is_ctor {\n                        format!(\n                            \"{:>6} = {:18} {:14} // \\\"{}\\\":{}\",\n                            pos, \"NameAndType\", index, name, desc\n                        )\n                    } else {\n                        format!(\n                            \"{:>6} = {:18} {:14} // {}:{}\",\n                            pos, \"NameAndType\", index, name, desc\n                        )\n                    };\n\n                    pool.push(v);\n                }\n                Type::Utf8 { bytes } => {\n                    let v = format!(\n                        \"{:>6} = {:18} {}\",\n                        pos,\n                        \"Utf8\",\n                        String::from_utf8_lossy(bytes.as_slice()).escape_default()\n                    );\n                    pool.push(v);\n                }\n                Type::MethodHandle {\n                    ref_kind: _,\n                    ref_index: _,\n                } => {\n                    pool.push(\"todo: MethodType\".to_string());\n                }\n                Type::MethodType { desc_index: _ } => {\n                    pool.push(\"todo: MethodType\".to_string());\n                }\n                Type::InvokeDynamic {\n                    bootstrap_method_attr_index: _,\n                    name_and_type_index: _,\n                } => {\n                    pool.push(\"todo: InvokeDynamic\".to_string());\n                }\n                Type::Unknown => (),\n            }\n        }\n\n        pool\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/field.rs",
    "content": "use crate::trans::AccessFlagsTranslator;\nuse crate::trans::SignatureTypeTranslator;\nuse class_parser::FieldSignature;\nuse classfile::{\n    constant_pool, constant_pool::Type as ConstantPoolType, BytesRef, ClassFile, FieldInfo,\n};\nuse handlebars::Handlebars;\n\npub struct FieldTranslation {\n    pub desc: String,\n    pub descriptor: String,\n    pub signature: String,\n    pub flags: String,\n    pub constant: String,\n}\n\npub struct Translator<'a> {\n    cf: &'a ClassFile,\n    field: &'a FieldInfo,\n}\n\nimpl<'a> Translator<'a> {\n    pub fn new(cf: &'a ClassFile, field: &'a FieldInfo) -> Self {\n        Self { cf, field }\n    }\n}\n\nimpl<'a> Translator<'a> {\n    pub fn get(&self) -> FieldTranslation {\n        let reg = Handlebars::new();\n        let flags = self.access_flags();\n        let desc = match flags.is_empty() {\n            true => {\n                let data = json!({\n                    \"type\": self.field_type(),\n                    \"name\": self.name(),\n                });\n\n                let tp = \"{{type}} {{name}};\";\n                reg.render_template(tp, &data).unwrap()\n            }\n            false => {\n                let data = json!({\n                    \"flags\": flags,\n                    \"type\": self.field_type(),\n                    \"name\": self.name(),\n                });\n\n                let tp = \"{{flags}} {{type}} {{name}};\";\n                reg.render_template(tp, &data).unwrap()\n            }\n        };\n\n        let descriptor = self.descriptor();\n        let signature = self.signature();\n        let flags = AccessFlagsTranslator::new(self.field.acc_flags).access_flag_inner();\n        let constant = self.attr_constant_value().unwrap_or(\"\".to_string());\n\n        FieldTranslation {\n            desc,\n            descriptor,\n            signature,\n            flags,\n            constant,\n        }\n    }\n}\n\nimpl<'a> Translator<'a> {\n    fn access_flags(&self) -> String {\n        let flags = self.field.acc_flags;\n        let t = AccessFlagsTranslator::new(flags);\n        t.field_access_flags()\n    }\n\n    fn field_type(&self) -> String {\n        let desc = constant_pool::get_utf8(&self.cf.cp, self.field.desc_index as usize).unwrap();\n        let signature = FieldSignature::new(desc.as_slice());\n        signature.field_type.into_string()\n    }\n\n    fn name(&self) -> String {\n        let name = constant_pool::get_utf8(&self.cf.cp, self.field.name_index as usize).unwrap();\n        String::from_utf8_lossy(name.as_slice()).to_string()\n    }\n\n    fn descriptor(&self) -> String {\n        let desc = constant_pool::get_utf8(&self.cf.cp, self.field.desc_index as usize).unwrap();\n        String::from_utf8_lossy(desc.as_slice()).to_string()\n    }\n\n    fn signature(&self) -> String {\n        self.attr_signature().map_or(\"\".to_string(), |(idx, v)| {\n            format!(\"#{:<28} // {}\", idx, String::from_utf8_lossy(v.as_slice()))\n        })\n    }\n\n    fn attr_signature(&self) -> Option<(usize, BytesRef)> {\n        self.field.attrs.iter().find_map(|v| {\n            if let classfile::attributes::Type::Signature { signature_index } = v {\n                let signature_index = *signature_index as usize;\n                let v = constant_pool::get_utf8(&self.cf.cp, signature_index).unwrap();\n                Some((signature_index, v))\n            } else {\n                None\n            }\n        })\n    }\n\n    fn attr_constant_value(&self) -> Option<String> {\n        let idx = self.field.attrs.iter().find_map(|v| {\n            if let classfile::attributes::Type::ConstantValue {\n                constant_value_index,\n            } = v\n            {\n                Some(*constant_value_index as usize)\n            } else {\n                None\n            }\n        });\n\n        idx.map(|idx| match self.cf.cp.get(idx) {\n            Some(ConstantPoolType::Long { v }) => {\n                let v = i64::from_be_bytes([v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]]);\n                format!(\"long {}\", v)\n            }\n            Some(ConstantPoolType::Float { v }) => {\n                let v = u32::from_be_bytes([v[0], v[1], v[2], v[3]]);\n                let v = f32::from_bits(v);\n                format!(\"float {}\", v)\n            }\n            Some(ConstantPoolType::Double { v }) => {\n                let v = u64::from_be_bytes([v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]]);\n                let v = f64::from_bits(v);\n                format!(\"double {}\", v)\n            }\n            Some(ConstantPoolType::Integer { v }) => {\n                let v = i32::from_be_bytes([v[0], v[1], v[2], v[3]]);\n                format!(\"int {}\", v)\n            }\n            Some(ConstantPoolType::String { string_index: _ }) => {\n                let v = constant_pool::get_string(&self.cf.cp, idx).unwrap();\n                format!(\"String {}\", v.escape_default())\n            }\n            _ => format!(\"todo\"),\n        })\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/aaload.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Aaload;\n\nimpl Instruction for Aaload {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::aaload,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/aastore.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Aastore;\n\nimpl Instruction for Aastore {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::aastore,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/aconst_null.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Aconst_Null;\n\nimpl Instruction for Aconst_Null {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::aconst_null,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/aload.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Aload {\n    pub wide: bool,\n}\n\nimpl Instruction for Aload {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let mut info = InstructionInfo {\n            pc,\n            op_code: OpCode::aload,\n            icp: 0,\n            wide: false,\n        };\n\n        if self.wide {\n            info.wide = self.wide;\n            (info, pc + 3)\n        } else {\n            (info, pc + 2)\n        }\n    }\n\n    fn set_wide(&mut self, wide: bool) {\n        self.wide = wide;\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/aload_0.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Aload_0;\n\nimpl Instruction for Aload_0 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::aload_0,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/aload_1.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Aload_1;\n\nimpl Instruction for Aload_1 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::aload_1,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/aload_2.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Aload_2;\n\nimpl Instruction for Aload_2 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::aload_2,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/aload_3.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Aload_3;\n\nimpl Instruction for Aload_3 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::aload_3,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/anewarray.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Anewarray;\n\nimpl Instruction for Anewarray {\n    fn run(&self, codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::anewarray,\n            icp: self.calc_cp_index_u16(codes, pc),\n            wide: false,\n        };\n\n        (info, pc + 3)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/areturn.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Areturn;\n\nimpl Instruction for Areturn {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::areturn,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/arraylength.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Arraylength;\n\nimpl Instruction for Arraylength {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::arraylength,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/astore.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Astore {\n    pub wide: bool,\n}\n\nimpl Instruction for Astore {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let mut info = InstructionInfo {\n            pc,\n            op_code: OpCode::astore,\n            icp: 0,\n            wide: false,\n        };\n\n        if self.wide {\n            info.wide = self.wide;\n            (info, pc + 3)\n        } else {\n            (info, pc + 2)\n        }\n    }\n\n    fn set_wide(&mut self, wide: bool) {\n        self.wide = wide;\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/astore_0.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Astore_0;\n\nimpl Instruction for Astore_0 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::astore_0,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/astore_1.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Astore_1;\n\nimpl Instruction for Astore_1 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::astore_1,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/astore_2.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Astore_2;\n\nimpl Instruction for Astore_2 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::astore_2,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/astore_3.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Astore_3;\n\nimpl Instruction for Astore_3 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::astore_3,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/athrow.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Athrow;\n\nimpl Instruction for Athrow {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::athrow,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/baload.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Baload;\n\nimpl Instruction for Baload {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::baload,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/bastore.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Bastore;\n\nimpl Instruction for Bastore {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::bastore,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/bipush.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Bipush;\n\nimpl Instruction for Bipush {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::bipush,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 2)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/caload.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Caload;\n\nimpl Instruction for Caload {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::caload,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/castore.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Castore;\n\nimpl Instruction for Castore {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::castore,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/checkcast.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Checkcast;\n\nimpl Instruction for Checkcast {\n    fn run(&self, codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::checkcast,\n            icp: self.calc_cp_index_u16(codes, pc),\n            wide: false,\n        };\n\n        (info, pc + 3)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/d2f.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct D2F;\n\nimpl Instruction for D2F {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::d2f,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/d2i.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct D2I;\n\nimpl Instruction for D2I {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::d2i,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/d2l.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct D2L;\n\nimpl Instruction for D2L {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::d2l,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/dadd.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Dadd;\n\nimpl Instruction for Dadd {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::dadd,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/daload.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Daload;\n\nimpl Instruction for Daload {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::daload,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 2)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/dastore.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Dastore;\n\nimpl Instruction for Dastore {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::dastore,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/dcmpg.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Dcmpg;\n\nimpl Instruction for Dcmpg {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::dcmpg,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/dcmpl.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Dcmpl;\n\nimpl Instruction for Dcmpl {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::dcmpl,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/dconst_0.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Dconst_0;\n\nimpl Instruction for Dconst_0 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::dconst_0,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/dconst_1.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Dconst_1;\n\nimpl Instruction for Dconst_1 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::dconst_1,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/ddiv.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Ddiv;\n\nimpl Instruction for Ddiv {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::ddiv,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/dload.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Dload {\n    pub wide: bool,\n}\n\nimpl Instruction for Dload {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let mut info = InstructionInfo {\n            pc,\n            op_code: OpCode::dload,\n            icp: 0,\n            wide: false,\n        };\n\n        if self.wide {\n            info.wide = self.wide;\n            (info, pc + 3)\n        } else {\n            (info, pc + 2)\n        }\n    }\n\n    fn set_wide(&mut self, wide: bool) {\n        self.wide = wide;\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/dload_0.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Dload_0;\n\nimpl Instruction for Dload_0 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::dload_0,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/dload_1.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Dload_1;\n\nimpl Instruction for Dload_1 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::dload_1,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/dload_2.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Dload_2;\n\nimpl Instruction for Dload_2 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::dload_2,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/dload_3.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Dload_3;\n\nimpl Instruction for Dload_3 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::dload_3,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/dmul.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Dmul;\n\nimpl Instruction for Dmul {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::dmul,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/dneg.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Dneg;\n\nimpl Instruction for Dneg {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::dneg,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/drem.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Drem;\n\nimpl Instruction for Drem {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::drem,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/dreturn.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Dreturn;\n\nimpl Instruction for Dreturn {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::dreturn,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/dstore.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Dstore {\n    pub wide: bool,\n}\n\nimpl Instruction for Dstore {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let mut info = InstructionInfo {\n            pc,\n            op_code: OpCode::dstore,\n            icp: 0,\n            wide: false,\n        };\n\n        if self.wide {\n            info.wide = self.wide;\n            (info, pc + 3)\n        } else {\n            (info, pc + 2)\n        }\n    }\n\n    fn set_wide(&mut self, wide: bool) {\n        self.wide = wide;\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/dstore_0.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Dstore_0;\n\nimpl Instruction for Dstore_0 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::dstore_0,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/dstore_1.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Dstore_1;\n\nimpl Instruction for Dstore_1 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::dstore_1,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/dstore_2.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Dstore_2;\n\nimpl Instruction for Dstore_2 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::dstore_2,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/dstore_3.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Dstore_3;\n\nimpl Instruction for Dstore_3 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::dstore_3,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/dsub.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Dsub;\n\nimpl Instruction for Dsub {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::dsub,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/dup.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Dup;\n\nimpl Instruction for Dup {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::dup,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/dup2.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Dup2;\n\nimpl Instruction for Dup2 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::dup2,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/dup2_x1.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Dup2_X1;\n\nimpl Instruction for Dup2_X1 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::dup2_x1,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/dup2_x2.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Dup2_X2;\n\nimpl Instruction for Dup2_X2 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::dup2_x2,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/dup_x1.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Dup_X1;\n\nimpl Instruction for Dup_X1 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::dup_x1,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/dup_x2.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Dup_X2;\n\nimpl Instruction for Dup_X2 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::dup_x2,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/f2d.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct F2D;\n\nimpl Instruction for F2D {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::f2d,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/f2i.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct F2I;\n\nimpl Instruction for F2I {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::f2i,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/f2l.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct F2L;\n\nimpl Instruction for F2L {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::f2l,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/fadd.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Fadd;\n\nimpl Instruction for Fadd {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::fadd,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/faload.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Faload;\n\nimpl Instruction for Faload {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::faload,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/fastore.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Fastore;\n\nimpl Instruction for Fastore {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::fastore,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/fcmpg.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Fcmpg;\n\nimpl Instruction for Fcmpg {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::fcmpg,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/fcmpl.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Fcmpl;\n\nimpl Instruction for Fcmpl {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::fcmpl,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/fconst_0.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Fconst_0;\n\nimpl Instruction for Fconst_0 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::fconst_0,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/fconst_1.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Fconst_1;\n\nimpl Instruction for Fconst_1 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::fconst_1,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/fconst_2.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Fconst_2;\n\nimpl Instruction for Fconst_2 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::fconst_2,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/fdiv.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Fdiv;\n\nimpl Instruction for Fdiv {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::fdiv,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/fload.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Fload {\n    pub wide: bool,\n}\n\nimpl Instruction for Fload {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let mut info = InstructionInfo {\n            pc,\n            op_code: OpCode::fload,\n            icp: 0,\n            wide: false,\n        };\n\n        if self.wide {\n            info.wide = self.wide;\n            (info, pc + 3)\n        } else {\n            (info, pc + 2)\n        }\n    }\n\n    fn set_wide(&mut self, wide: bool) {\n        self.wide = wide;\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/fload_0.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Fload_0;\n\nimpl Instruction for Fload_0 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::fload_0,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/fload_1.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Fload_1;\n\nimpl Instruction for Fload_1 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::fload_1,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/fload_2.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Fload_2;\n\nimpl Instruction for Fload_2 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::fload_2,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/fload_3.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Fload_3;\n\nimpl Instruction for Fload_3 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::fload_3,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/fmul.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Fmul;\n\nimpl Instruction for Fmul {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::fmul,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/fneg.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Fneg;\n\nimpl Instruction for Fneg {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::fneg,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/frem.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Frem;\n\nimpl Instruction for Frem {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::frem,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/freturn.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Freturn;\n\nimpl Instruction for Freturn {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::freturn,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/fstore.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Fstore {\n    pub wide: bool,\n}\n\nimpl Instruction for Fstore {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let mut info = InstructionInfo {\n            pc,\n            op_code: OpCode::fstore,\n            icp: 0,\n            wide: false,\n        };\n\n        if self.wide {\n            info.wide = self.wide;\n            (info, pc + 3)\n        } else {\n            (info, pc + 2)\n        }\n    }\n\n    fn set_wide(&mut self, wide: bool) {\n        self.wide = wide;\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/fstore_0.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Fstore_0;\n\nimpl Instruction for Fstore_0 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::fstore_0,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/fstore_1.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Fstore_1;\n\nimpl Instruction for Fstore_1 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::fstore_1,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/fstore_2.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Fstore_2;\n\nimpl Instruction for Fstore_2 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::fstore_2,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/fstore_3.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Fstore_3;\n\nimpl Instruction for Fstore_3 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::fstore_3,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/fsub.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Fsub;\n\nimpl Instruction for Fsub {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::fsub,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/getfield.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Getfield;\n\nimpl Instruction for Getfield {\n    fn run(&self, codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::getfield,\n            icp: self.calc_cp_index_u16(codes, pc),\n            wide: false,\n        };\n\n        (info, pc + 3)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/getstatic.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Getstatic;\n\nimpl Instruction for Getstatic {\n    fn run(&self, codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::getstatic,\n            icp: self.calc_cp_index_u16(codes, pc),\n            wide: false,\n        };\n\n        (info, pc + 3)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/goto.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Goto;\n\nimpl Instruction for Goto {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::goto,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 3)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/goto_w.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Goto_W;\n\nimpl Instruction for Goto_W {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::goto_w,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 5)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/i2b.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct I2B;\n\nimpl Instruction for I2B {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::i2b,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/i2c.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct I2C;\n\nimpl Instruction for I2C {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::i2c,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/i2d.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct I2D;\n\nimpl Instruction for I2D {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::i2d,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/i2f.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct I2F;\n\nimpl Instruction for I2F {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::i2f,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/i2l.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct I2L;\n\nimpl Instruction for I2L {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::i2l,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/i2s.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct I2S;\n\nimpl Instruction for I2S {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::i2s,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/iadd.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Iadd;\n\nimpl Instruction for Iadd {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::iadd,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/iaload.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Iaload;\n\nimpl Instruction for Iaload {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::iaload,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/iand.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Iand;\n\nimpl Instruction for Iand {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::iand,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/iastore.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Iastore;\n\nimpl Instruction for Iastore {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::iastore,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/iconst_0.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Iconst_0;\n\nimpl Instruction for Iconst_0 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::iconst_0,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/iconst_1.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Iconst_1;\n\nimpl Instruction for Iconst_1 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::iconst_1,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/iconst_2.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Iconst_2;\n\nimpl Instruction for Iconst_2 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::iconst_2,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/iconst_3.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Iconst_3;\n\nimpl Instruction for Iconst_3 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::iconst_3,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/iconst_4.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Iconst_4;\n\nimpl Instruction for Iconst_4 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::iconst_4,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/iconst_5.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Iconst_5;\n\nimpl Instruction for Iconst_5 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::iconst_5,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/iconst_m1.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Iconst_M1;\n\nimpl Instruction for Iconst_M1 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::iconst_m1,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/idiv.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Idiv;\n\nimpl Instruction for Idiv {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::idiv,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/if_acmpeq.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct If_Acmpeq;\n\nimpl Instruction for If_Acmpeq {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::if_acmpeq,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 3)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/if_acmpne.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct If_Acmpne;\n\nimpl Instruction for If_Acmpne {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::if_acmpne,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 3)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/if_icmpeq.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct If_Icmpeq;\n\nimpl Instruction for If_Icmpeq {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::if_icmpeq,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 3)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/if_icmpge.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct If_Icmpge;\n\nimpl Instruction for If_Icmpge {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::if_icmpge,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 3)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/if_icmpgt.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct If_Icmpgt;\n\nimpl Instruction for If_Icmpgt {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::if_icmpgt,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 3)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/if_icmple.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct If_Icmple;\n\nimpl Instruction for If_Icmple {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::if_icmple,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 3)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/if_icmplt.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct If_Icmplt;\n\nimpl Instruction for If_Icmplt {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::if_icmplt,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 3)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/if_icmpne.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct If_Icmpne;\n\nimpl Instruction for If_Icmpne {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::if_icmpne,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 3)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/ifeq.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Ifeq;\n\nimpl Instruction for Ifeq {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::ifeq,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 3)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/ifge.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Ifge;\n\nimpl Instruction for Ifge {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::ifge,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 3)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/ifgt.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Ifgt;\n\nimpl Instruction for Ifgt {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::ifgt,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 3)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/ifle.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Ifle;\n\nimpl Instruction for Ifle {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::ifle,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 3)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/iflt.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Iflt;\n\nimpl Instruction for Iflt {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::iflt,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 3)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/ifne.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Ifne;\n\nimpl Instruction for Ifne {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::ifne,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 3)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/ifnonnull.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Ifnonnull;\n\nimpl Instruction for Ifnonnull {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::ifnonnull,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 3)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/ifnull.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Ifnull;\n\nimpl Instruction for Ifnull {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::ifnull,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 3)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/iinc.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Iinc {\n    pub wide: bool,\n}\n\nimpl Instruction for Iinc {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let mut info = InstructionInfo {\n            pc,\n            op_code: OpCode::iinc,\n            icp: 0,\n            wide: false,\n        };\n\n        if self.wide {\n            info.wide = self.wide;\n            (info, pc + 5)\n        } else {\n            (info, pc + 3)\n        }\n    }\n\n    fn set_wide(&mut self, wide: bool) {\n        self.wide = wide;\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/iload.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Iload {\n    pub wide: bool,\n}\n\nimpl Instruction for Iload {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let mut info = InstructionInfo {\n            pc,\n            op_code: OpCode::iload,\n            icp: 0,\n            wide: false,\n        };\n\n        if self.wide {\n            info.wide = self.wide;\n            (info, pc + 3)\n        } else {\n            (info, pc + 2)\n        }\n    }\n\n    fn set_wide(&mut self, wide: bool) {\n        self.wide = wide;\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/iload_0.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Iload_0;\n\nimpl Instruction for Iload_0 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::iload_0,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/iload_1.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Iload_1;\n\nimpl Instruction for Iload_1 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::iload_1,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/iload_2.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Iload_2;\n\nimpl Instruction for Iload_2 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::iload_2,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/iload_3.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Iload_3;\n\nimpl Instruction for Iload_3 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::iload_3,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/imul.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Imul;\n\nimpl Instruction for Imul {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::imul,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/ineg.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Ineg;\n\nimpl Instruction for Ineg {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::ineg,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/instanceof.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Instanceof;\n\nimpl Instruction for Instanceof {\n    fn run(&self, codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::instanceof,\n            icp: self.calc_cp_index_u16(codes, pc),\n            wide: false,\n        };\n\n        (info, pc + 3)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/invokedynamic.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Invokedynamic;\n\nimpl Instruction for Invokedynamic {\n    fn run(&self, codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::invokedynamic,\n            icp: self.calc_cp_index_u16(codes, pc),\n            wide: false,\n        };\n\n        (info, pc + 5)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/invokeinterface.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Invokeinterface;\n\nimpl Instruction for Invokeinterface {\n    fn run(&self, codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::invokeinterface,\n            icp: self.calc_cp_index_u16(codes, pc),\n            wide: false,\n        };\n\n        (info, pc + 5)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/invokespecial.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Invokespecial;\n\nimpl Instruction for Invokespecial {\n    fn run(&self, codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::invokespecial,\n            icp: self.calc_cp_index_u16(codes, pc),\n            wide: false,\n        };\n\n        (info, pc + 3)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/invokestatic.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Invokestatic;\n\nimpl Instruction for Invokestatic {\n    fn run(&self, codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::invokestatic,\n            icp: self.calc_cp_index_u16(codes, pc),\n            wide: false,\n        };\n\n        (info, pc + 3)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/invokevirtual.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Invokevirtual;\n\nimpl Instruction for Invokevirtual {\n    fn run(&self, codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::invokevirtual,\n            icp: self.calc_cp_index_u16(codes, pc),\n            wide: false,\n        };\n\n        (info, pc + 3)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/ior.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Ior;\n\nimpl Instruction for Ior {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::ior,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/irem.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Irem;\n\nimpl Instruction for Irem {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::irem,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/ireturn.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Ireturn;\n\nimpl Instruction for Ireturn {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::ireturn,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/ishl.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Ishl;\n\nimpl Instruction for Ishl {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::ishl,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/ishr.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Ishr;\n\nimpl Instruction for Ishr {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::ishr,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/istore.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Istore {\n    pub wide: bool,\n}\n\nimpl Instruction for Istore {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let mut info = InstructionInfo {\n            pc,\n            op_code: OpCode::istore,\n            icp: 0,\n            wide: false,\n        };\n\n        if self.wide {\n            info.wide = self.wide;\n            (info, pc + 3)\n        } else {\n            (info, pc + 2)\n        }\n    }\n\n    fn set_wide(&mut self, wide: bool) {\n        self.wide = wide;\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/istore_0.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Istore_0;\n\nimpl Instruction for Istore_0 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::istore_0,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/istore_1.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Istore_1;\n\nimpl Instruction for Istore_1 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::istore_1,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/istore_2.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Istore_2;\n\nimpl Instruction for Istore_2 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::istore_2,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/istore_3.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Istore_3;\n\nimpl Instruction for Istore_3 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::istore_3,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/isub.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Isub;\n\nimpl Instruction for Isub {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::isub,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/iushr.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Iushr;\n\nimpl Instruction for Iushr {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::iushr,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/ixor.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Ixor;\n\nimpl Instruction for Ixor {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::ixor,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/jsr.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Jsr;\n\nimpl Instruction for Jsr {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::jsr,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 3)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/jsr_w.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Jsr_W;\n\nimpl Instruction for Jsr_W {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::jsr_w,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 5)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/l2d.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct L2D;\n\nimpl Instruction for L2D {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::l2d,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/l2f.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct L2F;\n\nimpl Instruction for L2F {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::l2f,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/l2i.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct L2I;\n\nimpl Instruction for L2I {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::l2i,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/ladd.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Ladd;\n\nimpl Instruction for Ladd {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::ladd,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/laload.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Laload;\n\nimpl Instruction for Laload {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::laload,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/land.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Land;\n\nimpl Instruction for Land {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::land,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/lastore.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Lastore;\n\nimpl Instruction for Lastore {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::lastore,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/lcmp.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Lcmp;\n\nimpl Instruction for Lcmp {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::lcmp,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/lconst_0.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Lconst_0;\n\nimpl Instruction for Lconst_0 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::lconst_0,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/lconst_1.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Lconst_1;\n\nimpl Instruction for Lconst_1 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::lconst_1,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/ldc.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Ldc;\n\nimpl Instruction for Ldc {\n    fn run(&self, codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::ldc,\n            icp: codes[pc + 1] as usize,\n            wide: false,\n        };\n\n        (info, pc + 2)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/ldc2_w.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Ldc2_W;\n\nimpl Instruction for Ldc2_W {\n    fn run(&self, codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::ldc2_w,\n            icp: self.calc_cp_index_u16(codes, pc),\n            wide: false,\n        };\n\n        (info, pc + 3)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/ldc_w.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Ldc_W;\n\nimpl Instruction for Ldc_W {\n    fn run(&self, codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::ldc_w,\n            icp: self.calc_cp_index_u16(codes, pc),\n            wide: false,\n        };\n\n        (info, pc + 3)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/ldiv.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Ldiv;\n\nimpl Instruction for Ldiv {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::ldiv,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/lload.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Lload {\n    pub wide: bool,\n}\n\nimpl Instruction for Lload {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let mut info = InstructionInfo {\n            pc,\n            op_code: OpCode::lload,\n            icp: 0,\n            wide: false,\n        };\n\n        if self.wide {\n            info.wide = self.wide;\n            (info, pc + 3)\n        } else {\n            (info, pc + 2)\n        }\n    }\n\n    fn set_wide(&mut self, wide: bool) {\n        self.wide = wide;\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/lload_0.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Lload_0;\n\nimpl Instruction for Lload_0 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::lload_0,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/lload_1.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Lload_1;\n\nimpl Instruction for Lload_1 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::lload_1,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/lload_2.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Lload_2;\n\nimpl Instruction for Lload_2 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::lload_2,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/lload_3.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Lload_3;\n\nimpl Instruction for Lload_3 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::lload_3,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/lmul.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Lmul;\n\nimpl Instruction for Lmul {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::lmul,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/lneg.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Lneg;\n\nimpl Instruction for Lneg {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::lneg,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/lookupswitch.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Lookupswitch;\n\nimpl Instruction for Lookupswitch {\n    fn run(&self, codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::lookupswitch,\n            icp: 0,\n            wide: false,\n        };\n\n        let mut bc = pc;\n        if bc % 4 != 0 {\n            bc += 4 - bc % 4;\n        } else {\n            bc += 4;\n        }\n        let mut ptr = bc as usize;\n\n        let default_byte = [codes[ptr], codes[ptr + 1], codes[ptr + 2], codes[ptr + 3]];\n        let _default_byte = u32::from_be_bytes(default_byte);\n        let count = [\n            codes[ptr + 4],\n            codes[ptr + 5],\n            codes[ptr + 6],\n            codes[ptr + 7],\n        ];\n        let count = u32::from_be_bytes(count);\n        ptr += 8;\n        ptr += (8 * count) as usize;\n\n        (info, ptr)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/lor.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Lor;\n\nimpl Instruction for Lor {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::lor,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/lrem.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Lrem;\n\nimpl Instruction for Lrem {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::lrem,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/lreturn.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Lreturn;\n\nimpl Instruction for Lreturn {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::lreturn,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/lshl.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Lshl;\n\nimpl Instruction for Lshl {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::lshl,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/lshr.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Lshr;\n\nimpl Instruction for Lshr {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::lshr,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/lstore.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Lstore {\n    pub wide: bool,\n}\n\nimpl Instruction for Lstore {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let mut info = InstructionInfo {\n            pc,\n            op_code: OpCode::lstore,\n            icp: 0,\n            wide: false,\n        };\n\n        if self.wide {\n            info.wide = self.wide;\n            (info, pc + 3)\n        } else {\n            (info, pc + 2)\n        }\n    }\n\n    fn set_wide(&mut self, wide: bool) {\n        self.wide = wide;\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/lstore_0.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Lstore_0;\n\nimpl Instruction for Lstore_0 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::lstore_0,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/lstore_1.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Lstore_1;\n\nimpl Instruction for Lstore_1 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::lstore_1,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/lstore_2.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Lstore_2;\n\nimpl Instruction for Lstore_2 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::lstore_2,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/lstore_3.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Lstore_3;\n\nimpl Instruction for Lstore_3 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::lstore_3,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/lsub.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Lsub;\n\nimpl Instruction for Lsub {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::lsub,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/lushr.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Lushr;\n\nimpl Instruction for Lushr {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::lushr,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/lxor.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Lxor;\n\nimpl Instruction for Lxor {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::lxor,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/mod.rs",
    "content": "mod aaload;\nmod aastore;\nmod aconst_null;\nmod aload;\nmod aload_0;\nmod aload_1;\nmod aload_2;\nmod aload_3;\nmod anewarray;\nmod areturn;\nmod arraylength;\nmod astore;\nmod astore_0;\nmod astore_1;\nmod astore_2;\nmod astore_3;\nmod athrow;\nmod baload;\nmod bastore;\nmod bipush;\nmod caload;\nmod castore;\nmod checkcast;\nmod d2f;\nmod d2i;\nmod d2l;\nmod dadd;\nmod daload;\nmod dastore;\nmod dcmpg;\nmod dcmpl;\nmod dconst_0;\nmod dconst_1;\nmod ddiv;\nmod dload;\nmod dload_0;\nmod dload_1;\nmod dload_2;\nmod dload_3;\nmod dmul;\nmod dneg;\nmod drem;\nmod dreturn;\nmod dstore;\nmod dstore_0;\nmod dstore_1;\nmod dstore_2;\nmod dstore_3;\nmod dsub;\nmod dup;\nmod dup2;\nmod dup2_x1;\nmod dup2_x2;\nmod dup_x1;\nmod dup_x2;\nmod f2d;\nmod f2i;\nmod f2l;\nmod fadd;\nmod faload;\nmod fastore;\nmod fcmpg;\nmod fcmpl;\nmod fconst_0;\nmod fconst_1;\nmod fconst_2;\nmod fdiv;\nmod fload;\nmod fload_0;\nmod fload_1;\nmod fload_2;\nmod fload_3;\nmod fmul;\nmod fneg;\nmod frem;\nmod freturn;\nmod fstore;\nmod fstore_0;\nmod fstore_1;\nmod fstore_2;\nmod fstore_3;\nmod fsub;\nmod getfield;\nmod getstatic;\nmod goto;\nmod goto_w;\nmod i2b;\nmod i2c;\nmod i2d;\nmod i2f;\nmod i2l;\nmod i2s;\nmod iadd;\nmod iaload;\nmod iand;\nmod iastore;\nmod iconst_0;\nmod iconst_1;\nmod iconst_2;\nmod iconst_3;\nmod iconst_4;\nmod iconst_5;\nmod iconst_m1;\nmod idiv;\nmod if_acmpeq;\nmod if_acmpne;\nmod if_icmpeq;\nmod if_icmpge;\nmod if_icmpgt;\nmod if_icmple;\nmod if_icmplt;\nmod if_icmpne;\nmod ifeq;\nmod ifge;\nmod ifgt;\nmod ifle;\nmod iflt;\nmod ifne;\nmod ifnonnull;\nmod ifnull;\nmod iinc;\nmod iload;\nmod iload_0;\nmod iload_1;\nmod iload_2;\nmod iload_3;\nmod imul;\nmod ineg;\nmod instanceof;\nmod invokedynamic;\nmod invokeinterface;\nmod invokespecial;\nmod invokestatic;\nmod invokevirtual;\nmod ior;\nmod irem;\nmod ireturn;\nmod ishl;\nmod ishr;\nmod istore;\nmod istore_0;\nmod istore_1;\nmod istore_2;\nmod istore_3;\nmod isub;\nmod iushr;\nmod ixor;\nmod jsr;\nmod jsr_w;\nmod l2d;\nmod l2f;\nmod l2i;\nmod ladd;\nmod laload;\nmod land;\nmod lastore;\nmod lcmp;\nmod lconst_0;\nmod lconst_1;\nmod ldc;\nmod ldc2_w;\nmod ldc_w;\nmod ldiv;\nmod lload;\nmod lload_0;\nmod lload_1;\nmod lload_2;\nmod lload_3;\nmod lmul;\nmod lneg;\nmod lookupswitch;\nmod lor;\nmod lrem;\nmod lreturn;\nmod lshl;\nmod lshr;\nmod lstore;\nmod lstore_0;\nmod lstore_1;\nmod lstore_2;\nmod lstore_3;\nmod lsub;\nmod lushr;\nmod lxor;\nmod monitorenter;\nmod monitorexit;\nmod multianewarray;\nmod new;\nmod newarray;\nmod nop;\nmod pop;\nmod pop2;\nmod putfield;\nmod putstatic;\nmod ret;\nmod return_void;\nmod saload;\nmod sastore;\nmod sipush;\nmod swap;\nmod tableswitch;\nmod wide;\n\nuse aaload::Aaload;\nuse aastore::Aastore;\nuse aconst_null::Aconst_Null;\nuse aload::Aload;\nuse aload_0::Aload_0;\nuse aload_1::Aload_1;\nuse aload_2::Aload_2;\nuse aload_3::Aload_3;\nuse anewarray::Anewarray;\nuse areturn::Areturn;\nuse arraylength::Arraylength;\nuse astore::Astore;\nuse astore_0::Astore_0;\nuse astore_1::Astore_1;\nuse astore_2::Astore_2;\nuse astore_3::Astore_3;\nuse athrow::Athrow;\nuse baload::Baload;\nuse bastore::Bastore;\nuse bipush::Bipush;\nuse caload::Caload;\nuse castore::Castore;\nuse checkcast::Checkcast;\nuse classfile::OpCode;\nuse d2f::D2F;\nuse d2i::D2I;\nuse d2l::D2L;\nuse dadd::Dadd;\nuse daload::Daload;\nuse dastore::Dastore;\nuse dcmpg::Dcmpg;\nuse dcmpl::Dcmpl;\nuse dconst_0::Dconst_0;\nuse dconst_1::Dconst_1;\nuse ddiv::Ddiv;\nuse dload::Dload;\nuse dload_0::Dload_0;\nuse dload_1::Dload_1;\nuse dload_2::Dload_2;\nuse dload_3::Dload_3;\nuse dmul::Dmul;\nuse dneg::Dneg;\nuse drem::Drem;\nuse dreturn::Dreturn;\nuse dstore::Dstore;\nuse dstore_0::Dstore_0;\nuse dstore_1::Dstore_1;\nuse dstore_2::Dstore_2;\nuse dstore_3::Dstore_3;\nuse dsub::Dsub;\nuse dup::Dup;\nuse dup2::Dup2;\nuse dup2_x1::Dup2_X1;\nuse dup2_x2::Dup2_X2;\nuse dup_x1::Dup_X1;\nuse dup_x2::Dup_X2;\nuse f2d::F2D;\nuse f2i::F2I;\nuse f2l::F2L;\nuse fadd::Fadd;\nuse faload::Faload;\nuse fastore::Fastore;\nuse fcmpg::Fcmpg;\nuse fcmpl::Fcmpl;\nuse fconst_0::Fconst_0;\nuse fconst_1::Fconst_1;\nuse fconst_2::Fconst_2;\nuse fdiv::Fdiv;\nuse fload::Fload;\nuse fload_0::Fload_0;\nuse fload_1::Fload_1;\nuse fload_2::Fload_2;\nuse fload_3::Fload_3;\nuse fmul::Fmul;\nuse fneg::Fneg;\nuse frem::Frem;\nuse freturn::Freturn;\nuse fstore::Fstore;\nuse fstore_0::Fstore_0;\nuse fstore_1::Fstore_1;\nuse fstore_2::Fstore_2;\nuse fstore_3::Fstore_3;\nuse fsub::Fsub;\nuse getfield::Getfield;\nuse getstatic::Getstatic;\nuse goto::Goto;\nuse goto_w::Goto_W;\nuse i2b::I2B;\nuse i2c::I2C;\nuse i2d::I2D;\nuse i2f::I2F;\nuse i2l::I2L;\nuse i2s::I2S;\nuse iadd::Iadd;\nuse iaload::Iaload;\nuse iand::Iand;\nuse iastore::Iastore;\nuse iconst_0::Iconst_0;\nuse iconst_1::Iconst_1;\nuse iconst_2::Iconst_2;\nuse iconst_3::Iconst_3;\nuse iconst_4::Iconst_4;\nuse iconst_5::Iconst_5;\nuse iconst_m1::Iconst_M1;\nuse idiv::Idiv;\nuse if_acmpeq::If_Acmpeq;\nuse if_acmpne::If_Acmpne;\nuse if_icmpeq::If_Icmpeq;\nuse if_icmpge::If_Icmpge;\nuse if_icmpgt::If_Icmpgt;\nuse if_icmple::If_Icmple;\nuse if_icmplt::If_Icmplt;\nuse if_icmpne::If_Icmpne;\nuse ifeq::Ifeq;\nuse ifge::Ifge;\nuse ifgt::Ifgt;\nuse ifle::Ifle;\nuse iflt::Iflt;\nuse ifne::Ifne;\nuse ifnonnull::Ifnonnull;\nuse ifnull::Ifnull;\nuse iinc::Iinc;\nuse iload::Iload;\nuse iload_0::Iload_0;\nuse iload_1::Iload_1;\nuse iload_2::Iload_2;\nuse iload_3::Iload_3;\nuse imul::Imul;\nuse ineg::Ineg;\nuse instanceof::Instanceof;\nuse invokedynamic::Invokedynamic;\nuse invokeinterface::Invokeinterface;\nuse invokespecial::Invokespecial;\nuse invokestatic::Invokestatic;\nuse invokevirtual::Invokevirtual;\nuse ior::Ior;\nuse irem::Irem;\nuse ireturn::Ireturn;\nuse ishl::Ishl;\nuse ishr::Ishr;\nuse istore::Istore;\nuse istore_0::Istore_0;\nuse istore_1::Istore_1;\nuse istore_2::Istore_2;\nuse istore_3::Istore_3;\nuse isub::Isub;\nuse iushr::Iushr;\nuse ixor::Ixor;\nuse jsr::Jsr;\nuse jsr_w::Jsr_W;\nuse l2d::L2D;\nuse l2f::L2F;\nuse l2i::L2I;\nuse ladd::Ladd;\nuse laload::Laload;\nuse land::Land;\nuse lastore::Lastore;\nuse lcmp::Lcmp;\nuse lconst_0::Lconst_0;\nuse lconst_1::Lconst_1;\nuse ldc::Ldc;\nuse ldc2_w::Ldc2_W;\nuse ldc_w::Ldc_W;\nuse ldiv::Ldiv;\nuse lload::Lload;\nuse lload_0::Lload_0;\nuse lload_1::Lload_1;\nuse lload_2::Lload_2;\nuse lload_3::Lload_3;\nuse lmul::Lmul;\nuse lneg::Lneg;\nuse lookupswitch::Lookupswitch;\nuse lor::Lor;\nuse lrem::Lrem;\nuse lreturn::Lreturn;\nuse lshl::Lshl;\nuse lshr::Lshr;\nuse lstore::Lstore;\nuse lstore_0::Lstore_0;\nuse lstore_1::Lstore_1;\nuse lstore_2::Lstore_2;\nuse lstore_3::Lstore_3;\nuse lsub::Lsub;\nuse lushr::Lushr;\nuse lxor::Lxor;\nuse monitorenter::Monitorenter;\nuse monitorexit::Monitorexit;\nuse multianewarray::Multianewarray;\nuse new::New;\nuse newarray::Newarray;\nuse nop::Nop;\nuse pop::Pop;\nuse pop2::Pop2;\nuse putfield::Putfield;\nuse putstatic::Putstatic;\nuse ret::Ret;\nuse return_void::Return_Void;\nuse saload::Saload;\nuse sastore::Sastore;\nuse sipush::Sipush;\nuse swap::Swap;\nuse tableswitch::Tableswitch;\nuse wide::Wide;\n\nuse classfile::constant_pool::Type;\nuse classfile::{constant_pool, ConstantPool, ConstantPoolType};\n\npub struct InstructionInfo {\n    pub pc: usize,\n    pub op_code: OpCode,\n    pub icp: usize,\n    pub wide: bool,\n}\n\nimpl InstructionInfo {\n    pub fn assemble(&self, codes: &[u8], cp: &ConstantPool) -> String {\n        let op_code: &'static str = self.op_code.into();\n        if self.icp != 0 {\n            let comment = self.comment(cp);\n            match self.op_code {\n                OpCode::invokeinterface => {\n                    let count = codes[self.pc + 3];\n                    let stack_info = format!(\"#{}, {:2}\", self.icp, count);\n                    format!(\n                        \"{:>4}: {:15} {:<20} // {}\",\n                        self.pc, op_code, stack_info, comment\n                    )\n                }\n                _ => format!(\n                    \"{:>4}: {:15} #{:<20}// {}\",\n                    self.pc, op_code, self.icp, comment\n                ),\n            }\n        } else {\n            match self.op_code {\n                OpCode::aload\n                | OpCode::iload\n                | OpCode::fload\n                | OpCode::lload\n                | OpCode::dload\n                | OpCode::istore\n                | OpCode::fstore\n                | OpCode::astore\n                | OpCode::lstore\n                | OpCode::dstore\n                | OpCode::ret => {\n                    if self.wide {\n                        let index = construct_usize(codes, self.pc);\n                        format!(\"{:>4}: {:15} {}\", self.pc, op_code, index)\n                    } else {\n                        let index = codes[self.pc + 1];\n                        format!(\"{:>4}: {:15} {}\", self.pc, op_code, index)\n                    }\n                }\n                OpCode::if_acmpeq\n                | OpCode::if_acmpne\n                | OpCode::if_icmpeq\n                | OpCode::if_icmpne\n                | OpCode::if_icmplt\n                | OpCode::if_icmpge\n                | OpCode::if_icmpgt\n                | OpCode::if_icmple\n                | OpCode::ifeq\n                | OpCode::ifne\n                | OpCode::iflt\n                | OpCode::ifge\n                | OpCode::ifgt\n                | OpCode::ifle\n                | OpCode::ifnonnull\n                | OpCode::ifnull\n                | OpCode::goto => {\n                    let branch = construct_i16(codes, self.pc);\n                    let target = self.pc as i32 + branch as i32;\n                    format!(\"{:>4}: {:15} {}\", self.pc, op_code, target)\n                }\n                OpCode::iinc => {\n                    if self.wide {\n                        let index = construct_usize(codes, self.pc);\n                        let const_v = {\n                            let pc = self.pc;\n                            let constbyte1 = codes[pc + 3] as i16;\n                            let constbyte2 = codes[pc + 4] as i16;\n                            constbyte1 << 8 | constbyte2\n                        };\n                        format!(\"{:>4}: {:15} {}, {}\", self.pc, op_code, index, const_v)\n                    } else {\n                        let index = codes[self.pc + 1];\n                        let const_v = (codes[self.pc + 2] as i8) as i32;\n                        format!(\"{:>4}: {:15} {}, {}\", self.pc, op_code, index, const_v)\n                    }\n                }\n                OpCode::sipush => {\n                    let v = construct_i16(codes, self.pc);\n                    format!(\"{:>4}: {:15} {}\", self.pc, op_code, v)\n                }\n                _ => format!(\"{:>4}: {:15}\", self.pc, op_code),\n            }\n        }\n    }\n\n    fn comment(&self, cp: &ConstantPool) -> String {\n        assert_ne!(0, self.icp);\n\n        match cp.get(self.icp).unwrap() {\n            ConstantPoolType::Class { name_index } => {\n                let class_name = constant_pool::get_utf8(cp, *name_index as usize).unwrap();\n                let is_ary_class = class_name.starts_with(b\"[\");\n                let class_name = String::from_utf8_lossy(class_name.as_slice()).to_string();\n                if is_ary_class {\n                    format!(\"class \\\"{}\\\"\", class_name)\n                } else {\n                    format!(\"class {}\", class_name)\n                }\n            }\n            ConstantPoolType::FieldRef {\n                class_index: _,\n                name_and_type_index,\n            } => {\n                // let class_name = constant_pool::get_class_name(cp, *class_index as usize).unwrap();\n                // let class_name = String::from_utf8_lossy(class_name.as_slice());\n                let (name, desc) =\n                    constant_pool::get_name_and_type(cp, *name_and_type_index as usize);\n                let name = name.unwrap();\n                let desc = desc.unwrap();\n                let name = String::from_utf8_lossy(name.as_slice());\n                let desc = String::from_utf8_lossy(desc.as_slice());\n                format!(\"Field {}:{}\", name, desc)\n            }\n            ConstantPoolType::MethodRef {\n                class_index,\n                name_and_type_index,\n            } => {\n                let class_name = constant_pool::get_class_name(cp, *class_index as usize).unwrap();\n                let is_ary_class = class_name.starts_with(b\"[\");\n                let class_name = String::from_utf8_lossy(class_name.as_slice());\n                let (name, desc) =\n                    constant_pool::get_name_and_type(cp, *name_and_type_index as usize);\n                let name = name.unwrap();\n                let desc = desc.unwrap();\n                let is_ctor = name.as_slice() == b\"<init>\";\n                let desc = String::from_utf8_lossy(desc.as_slice());\n                if is_ctor {\n                    format!(\"Method {}.\\\"<init>\\\":{}\", class_name, desc)\n                } else {\n                    let name = String::from_utf8_lossy(name.as_slice());\n                    if is_ary_class {\n                        format!(\"Method \\\"{}\\\".{}:{}\", class_name, name, desc)\n                    } else {\n                        format!(\"Method {}.{}:{}\", class_name, name, desc)\n                    }\n                }\n            }\n            ConstantPoolType::String { string_index: _ } => {\n                let v = constant_pool::get_string(cp, self.icp).unwrap();\n                format!(\"String {}\", v.escape_default())\n            }\n            ConstantPoolType::Float { v } => {\n                let v = u32::from_be_bytes([v[0], v[1], v[2], v[3]]);\n                let v = f32::from_bits(v);\n                format!(\"float {}f\", v)\n            }\n            ConstantPoolType::Double { v } => {\n                let v = u64::from_be_bytes([v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]]);\n                let v = f64::from_bits(v);\n                format!(\"double {}d\", v)\n            }\n            ConstantPoolType::Long { v } => {\n                let v = i64::from_be_bytes([v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]]);\n                format!(\"long {}l\", v)\n            }\n            Type::Nop => unreachable!(),\n            Type::InterfaceMethodRef {\n                class_index,\n                name_and_type_index,\n            } => {\n                let class_name = constant_pool::get_class_name(cp, *class_index as usize).unwrap();\n                let name_and_type =\n                    constant_pool::get_name_and_type(cp, *name_and_type_index as usize);\n                let method_name = name_and_type.0.unwrap();\n                let method_type = name_and_type.1.unwrap();\n                format!(\n                    \"InterfaceMethod {}.{}:{}\",\n                    String::from_utf8_lossy(class_name.as_slice()),\n                    String::from_utf8_lossy(method_name.as_slice()),\n                    String::from_utf8_lossy(method_type.as_slice())\n                )\n            }\n            Type::Integer { v } => {\n                let v = i32::from_be_bytes([v[0], v[1], v[2], v[3]]);\n                format!(\"int {}\", v)\n            }\n            Type::NameAndType {\n                name_index: _,\n                desc_index: _,\n            } => \"todo: NameAndType\".to_string(),\n            Type::Utf8 { bytes: _ } => \"todo: Utf8\".to_string(),\n            Type::MethodHandle {\n                ref_kind: _,\n                ref_index: _,\n            } => \"todo: MethodHandle\".to_string(),\n            Type::MethodType { desc_index: _ } => \"todo: MethodType\".to_string(),\n            Type::InvokeDynamic {\n                bootstrap_method_attr_index: _,\n                name_and_type_index: _,\n            } => \"todo: InvokeDynamic\".to_string(),\n            Type::Unknown => unreachable!(),\n        }\n    }\n}\n\nfn construct_usize(codes: &[u8], pc: usize) -> usize {\n    let indexbyte1 = codes[pc + 1] as u16;\n    let indexbyte2 = codes[pc + 2] as u16;\n    (indexbyte1 << 8 | indexbyte2) as usize\n}\n\nfn construct_i16(codes: &[u8], pc: usize) -> i16 {\n    let indexbyte1 = codes[pc + 1] as i16;\n    let indexbyte2 = codes[pc + 2] as i16;\n    indexbyte1 << 8 | indexbyte2\n}\n\npub trait Instruction {\n    fn run(&self, codes: &[u8], pc: usize) -> (InstructionInfo, usize);\n    fn calc_cp_index_u16(&self, codes: &[u8], pc: usize) -> usize {\n        construct_usize(codes, pc)\n    }\n    fn set_wide(&mut self, _wide: bool) {\n        unimplemented!()\n    }\n}\n\npub fn get_instructions() -> Vec<Box<dyn Instruction>> {\n    vec![\n        Box::new(Nop),\n        Box::new(Aconst_Null),\n        Box::new(Iconst_M1),\n        Box::new(Iconst_0),\n        Box::new(Iconst_1),\n        Box::new(Iconst_2),\n        Box::new(Iconst_3),\n        Box::new(Iconst_4),\n        Box::new(Iconst_5),\n        Box::new(Lconst_0),\n        Box::new(Lconst_1),\n        Box::new(Fconst_0),\n        Box::new(Fconst_1),\n        Box::new(Fconst_2),\n        Box::new(Dconst_0),\n        Box::new(Dconst_1),\n        Box::new(Bipush),\n        Box::new(Sipush),\n        Box::new(Ldc),\n        Box::new(Ldc_W),\n        Box::new(Ldc2_W),\n        Box::new(Iload { wide: false }),\n        Box::new(Lload { wide: false }),\n        Box::new(Fload { wide: false }),\n        Box::new(Dload { wide: false }),\n        Box::new(Aload { wide: false }),\n        Box::new(Iload_0),\n        Box::new(Iload_1),\n        Box::new(Iload_2),\n        Box::new(Iload_3),\n        Box::new(Lload_0),\n        Box::new(Lload_1),\n        Box::new(Lload_2),\n        Box::new(Lload_3),\n        Box::new(Fload_0),\n        Box::new(Fload_1),\n        Box::new(Fload_2),\n        Box::new(Fload_3),\n        Box::new(Dload_0),\n        Box::new(Dload_1),\n        Box::new(Dload_2),\n        Box::new(Dload_3),\n        Box::new(Aload_0),\n        Box::new(Aload_1),\n        Box::new(Aload_2),\n        Box::new(Aload_3),\n        Box::new(Iaload),\n        Box::new(Laload),\n        Box::new(Faload),\n        Box::new(Daload),\n        Box::new(Aaload),\n        Box::new(Baload),\n        Box::new(Caload),\n        Box::new(Saload),\n        Box::new(Istore { wide: false }),\n        Box::new(Lstore { wide: false }),\n        Box::new(Fstore { wide: false }),\n        Box::new(Dstore { wide: false }),\n        Box::new(Astore { wide: false }),\n        Box::new(Istore_0),\n        Box::new(Istore_1),\n        Box::new(Istore_2),\n        Box::new(Istore_3),\n        Box::new(Lstore_0),\n        Box::new(Lstore_1),\n        Box::new(Lstore_2),\n        Box::new(Lstore_3),\n        Box::new(Fstore_0),\n        Box::new(Fstore_1),\n        Box::new(Fstore_2),\n        Box::new(Fstore_3),\n        Box::new(Dstore_0),\n        Box::new(Dstore_1),\n        Box::new(Dstore_2),\n        Box::new(Dstore_3),\n        Box::new(Astore_0),\n        Box::new(Astore_1),\n        Box::new(Astore_2),\n        Box::new(Astore_3),\n        Box::new(Iastore),\n        Box::new(Lastore),\n        Box::new(Fastore),\n        Box::new(Dastore),\n        Box::new(Aastore),\n        Box::new(Bastore),\n        Box::new(Castore),\n        Box::new(Sastore),\n        Box::new(Pop),\n        Box::new(Pop2),\n        Box::new(Dup),\n        Box::new(Dup_X1),\n        Box::new(Dup_X2),\n        Box::new(Dup2),\n        Box::new(Dup2_X1),\n        Box::new(Dup2_X2),\n        Box::new(Swap),\n        Box::new(Iadd),\n        Box::new(Ladd),\n        Box::new(Fadd),\n        Box::new(Dadd),\n        Box::new(Isub),\n        Box::new(Lsub),\n        Box::new(Fsub),\n        Box::new(Dsub),\n        Box::new(Imul),\n        Box::new(Lmul),\n        Box::new(Fmul),\n        Box::new(Dmul),\n        Box::new(Idiv),\n        Box::new(Ldiv),\n        Box::new(Fdiv),\n        Box::new(Ddiv),\n        Box::new(Irem),\n        Box::new(Lrem),\n        Box::new(Frem),\n        Box::new(Drem),\n        Box::new(Ineg),\n        Box::new(Lneg),\n        Box::new(Fneg),\n        Box::new(Dneg),\n        Box::new(Ishl),\n        Box::new(Lshl),\n        Box::new(Ishr),\n        Box::new(Lshr),\n        Box::new(Iushr),\n        Box::new(Lushr),\n        Box::new(Iand),\n        Box::new(Land),\n        Box::new(Ior),\n        Box::new(Lor),\n        Box::new(Ixor),\n        Box::new(Lxor),\n        Box::new(Iinc { wide: false }),\n        Box::new(I2L),\n        Box::new(I2F),\n        Box::new(I2D),\n        Box::new(L2I),\n        Box::new(L2F),\n        Box::new(L2D),\n        Box::new(F2I),\n        Box::new(F2L),\n        Box::new(F2D),\n        Box::new(D2I),\n        Box::new(D2L),\n        Box::new(D2F),\n        Box::new(I2B),\n        Box::new(I2C),\n        Box::new(I2S),\n        Box::new(Lcmp),\n        Box::new(Fcmpl),\n        Box::new(Fcmpg),\n        Box::new(Dcmpl),\n        Box::new(Dcmpg),\n        Box::new(Ifeq),\n        Box::new(Ifne),\n        Box::new(Iflt),\n        Box::new(Ifge),\n        Box::new(Ifgt),\n        Box::new(Ifle),\n        Box::new(If_Icmpeq),\n        Box::new(If_Icmpne),\n        Box::new(If_Icmplt),\n        Box::new(If_Icmpge),\n        Box::new(If_Icmpgt),\n        Box::new(If_Icmple),\n        Box::new(If_Acmpeq),\n        Box::new(If_Acmpne),\n        Box::new(Goto),\n        Box::new(Jsr),\n        Box::new(Ret { wide: false }),\n        Box::new(Tableswitch),\n        Box::new(Lookupswitch),\n        Box::new(Ireturn),\n        Box::new(Lreturn),\n        Box::new(Freturn),\n        Box::new(Dreturn),\n        Box::new(Areturn),\n        Box::new(Return_Void),\n        Box::new(Getstatic),\n        Box::new(Putstatic),\n        Box::new(Getfield),\n        Box::new(Putfield),\n        Box::new(Invokevirtual),\n        Box::new(Invokespecial),\n        Box::new(Invokestatic),\n        Box::new(Invokeinterface),\n        Box::new(Invokedynamic),\n        Box::new(New),\n        Box::new(Newarray),\n        Box::new(Anewarray),\n        Box::new(Arraylength),\n        Box::new(Athrow),\n        Box::new(Checkcast),\n        Box::new(Instanceof),\n        Box::new(Monitorenter),\n        Box::new(Monitorexit),\n        Box::new(Wide),\n        Box::new(Multianewarray),\n        Box::new(Ifnull),\n        Box::new(Ifnonnull),\n        Box::new(Goto_W),\n        Box::new(Jsr_W),\n    ]\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/monitorenter.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Monitorenter;\n\nimpl Instruction for Monitorenter {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::monitorenter,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/monitorexit.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Monitorexit;\n\nimpl Instruction for Monitorexit {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::monitorexit,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/multianewarray.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Multianewarray;\n\nimpl Instruction for Multianewarray {\n    fn run(&self, codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::multianewarray,\n            icp: self.calc_cp_index_u16(codes, pc),\n            wide: false,\n        };\n\n        (info, pc + 4)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/new.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct New;\n\nimpl Instruction for New {\n    fn run(&self, codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::new,\n            icp: self.calc_cp_index_u16(codes, pc),\n            wide: false,\n        };\n\n        (info, pc + 3)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/newarray.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Newarray;\n\nimpl Instruction for Newarray {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::newarray,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 2)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/nop.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Nop;\n\nimpl Instruction for Nop {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::nop,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/pop.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Pop;\n\nimpl Instruction for Pop {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::pop,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/pop2.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Pop2;\n\nimpl Instruction for Pop2 {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::pop2,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/putfield.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Putfield;\n\nimpl Instruction for Putfield {\n    fn run(&self, codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::putfield,\n            icp: self.calc_cp_index_u16(codes, pc),\n            wide: false,\n        };\n\n        (info, pc + 3)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/putstatic.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Putstatic;\n\nimpl Instruction for Putstatic {\n    fn run(&self, codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::putstatic,\n            icp: self.calc_cp_index_u16(codes, pc),\n            wide: false,\n        };\n\n        (info, pc + 3)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/ret.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Ret {\n    pub wide: bool,\n}\n\nimpl Instruction for Ret {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let mut info = InstructionInfo {\n            pc,\n            op_code: OpCode::ret,\n            icp: 0,\n            wide: false,\n        };\n\n        if self.wide {\n            info.wide = self.wide;\n            (info, pc + 3)\n        } else {\n            (info, pc + 2)\n        }\n    }\n\n    fn set_wide(&mut self, wide: bool) {\n        self.wide = wide;\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/return_void.rs",
    "content": "#![allow(non_camel_case_types)]\nuse super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Return_Void;\n\nimpl Instruction for Return_Void {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::return_void,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/saload.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Saload;\n\nimpl Instruction for Saload {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::saload,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/sastore.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Sastore;\n\nimpl Instruction for Sastore {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::sastore,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/sipush.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Sipush;\n\nimpl Instruction for Sipush {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::sipush,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 3)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/swap.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Swap;\n\nimpl Instruction for Swap {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::swap,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/tableswitch.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Tableswitch;\n\nimpl Instruction for Tableswitch {\n    fn run(&self, codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::tableswitch,\n            icp: 0,\n            wide: false,\n        };\n\n        let mut bc = pc;\n        if bc % 4 != 0 {\n            bc += 4 - bc % 4;\n        } else {\n            bc += 4;\n        }\n        let mut ptr = bc as usize;\n        let default_byte = [codes[ptr], codes[ptr + 1], codes[ptr + 2], codes[ptr + 3]];\n        let _default_byte = i32::from_be_bytes(default_byte);\n        let low_byte = [\n            codes[ptr + 4],\n            codes[ptr + 5],\n            codes[ptr + 6],\n            codes[ptr + 7],\n        ];\n        let low_byte = i32::from_be_bytes(low_byte);\n        let high_byte = [\n            codes[ptr + 8],\n            codes[ptr + 9],\n            codes[ptr + 10],\n            codes[ptr + 11],\n        ];\n        let high_byte = i32::from_be_bytes(high_byte);\n        let num = high_byte - low_byte + 1;\n        ptr += 12;\n        ptr += (4 * num) as usize;\n\n        (info, ptr)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/instruction/wide.rs",
    "content": "use super::{Instruction, InstructionInfo};\nuse classfile::OpCode;\n\npub struct Wide;\n\nimpl Instruction for Wide {\n    fn run(&self, _codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\n        let info = InstructionInfo {\n            pc,\n            op_code: OpCode::wide,\n            icp: 0,\n            wide: false,\n        };\n\n        (info, pc + 1)\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/method.rs",
    "content": "use crate::sd::CodeSerde;\nuse crate::trans::SignatureTypeTranslator;\nuse crate::trans::{AccessFlagHelper, AccessFlagsTranslator, CodeTranslator};\nuse class_parser::MethodSignature;\nuse classfile::attributes::LocalVariable;\nuse classfile::{\n    attributes::LineNumber, attributes::StackMapFrame, attributes::VerificationTypeInfo,\n    constant_pool, BytesRef, ClassFile, MethodInfo,\n};\nuse handlebars::Handlebars;\n\npub struct MethodTranslation {\n    pub desc: String,\n    pub line_num_table: Vec<LineNumber>,\n    pub code: CodeSerde,\n    pub descriptor: String,\n    pub signature: String,\n    pub flags: String,\n    pub throws: String,\n    pub ex_table: Vec<String>,\n    pub stack_map_table: Vec<StackMapTableTranslation>,\n    pub local_variable_table: Vec<String>,\n    pub local_variable_type_table: Vec<String>,\n}\n\npub struct StackMapTableTranslation {\n    pub tag: u8,\n    pub comment: &'static str,\n    pub items: Vec<String>,\n}\n\npub struct Translator<'a> {\n    cf: &'a ClassFile,\n    method: &'a MethodInfo,\n}\n\nimpl<'a> Translator<'a> {\n    pub fn new(cf: &'a ClassFile, method: &'a MethodInfo) -> Self {\n        Self { cf, method }\n    }\n}\n\nimpl<'a> Translator<'a> {\n    pub fn get(&self, with_line_num: bool, with_code: bool) -> MethodTranslation {\n        let desc = self.build_desc();\n        let line_num_table = if with_line_num {\n            self.method.get_line_number_table()\n        } else {\n            vec![]\n        };\n        let code = if with_code {\n            self.code()\n        } else {\n            Default::default()\n        };\n        let descriptor = self.descriptor();\n        let descriptor = String::from_utf8_lossy(descriptor.as_slice()).to_string();\n        let signature = self.attr_signature().map_or_else(\n            || \"\".to_string(),\n            |(idx, v)| {\n                format!(\n                    \"#{:<28} // {}\",\n                    idx,\n                    String::from_utf8_lossy(v.as_slice()).to_string()\n                )\n            },\n        );\n        let flags = AccessFlagsTranslator::new(self.method.acc_flags).access_flag_inner();\n        let throws = self.throws().unwrap_or(\"\".to_string());\n        let ex_table = self.ex_table();\n        let stack_map_table = self.stack_map_table();\n        let local_variable_table = self.local_variable_table();\n        let local_variable_type_table = self.local_variable_type_table();\n\n        MethodTranslation {\n            desc,\n            line_num_table,\n            code,\n            descriptor,\n            signature,\n            flags,\n            throws,\n            ex_table,\n            stack_map_table,\n            local_variable_table,\n            local_variable_type_table,\n        }\n    }\n}\n\nimpl<'a> Translator<'a> {\n    fn build_desc(&self) -> String {\n        let name = constant_pool::get_utf8(&self.cf.cp, self.method.name_index as usize).unwrap();\n        let mut desc = match name.as_slice() {\n            b\"<clinit>\" => \"static {}\".to_string(),\n            _ => {\n                let mut reg = Handlebars::new();\n                reg.register_escape_fn(handlebars::no_escape);\n\n                let name = match name.as_slice() {\n                    b\"<init>\" => {\n                        let class_name =\n                            constant_pool::get_class_name(&self.cf.cp, self.cf.this_class as usize)\n                                .unwrap();\n                        String::from_utf8_lossy(class_name.as_slice()).replace(\"/\", \".\")\n                    }\n                    _ => String::from_utf8_lossy(name.as_slice()).to_string(),\n                };\n\n                let flags = self.access_flags();\n                match flags.is_empty() {\n                    true => {\n                        let data = json!({\n                            \"return_type\": self.return_type(),\n                            \"name\": name,\n                            \"args\": self.args().join(\", \")\n                        });\n\n                        let tp = \"{{return_type}} {{name}}({{args}})\";\n                        reg.render_template(tp, &data).unwrap()\n                    }\n                    false => {\n                        let data = json!({\n                            \"flags\": self.access_flags(),\n                            \"return_type\": self.return_type(),\n                            \"name\": name,\n                            \"args\": self.args().join(\", \")\n                        });\n\n                        let tp = \"{{flags}} {{return_type}} {{name}}({{args}})\";\n                        reg.render_template(tp, &data).unwrap()\n                    }\n                }\n            }\n        };\n\n        match self.throws() {\n            Some(ex) => {\n                desc.push_str(\" throws\");\n                desc.push_str(\" \");\n                desc.push_str(ex.as_str());\n                desc.push_str(\";\")\n            }\n            _ => desc.push_str(\";\"),\n        }\n\n        desc\n    }\n}\n\nimpl<'a> Translator<'a> {\n    fn access_flags(&self) -> String {\n        let flags = self.method.acc_flags;\n        let t = AccessFlagsTranslator::new(flags);\n        t.method_access_flags()\n    }\n\n    fn return_type(&self) -> String {\n        let signature = self.method_signature();\n        let mut retype = String::new();\n\n        /*\n            build generics, if exists\n\n        for example:\n        TestNG, org.testng.collections.Maps\n\n        <K:Ljava/lang/Object;V:Ljava/lang/Object;>(Ljava/util/Map<TK;TV;>;)Ljava/util/Map<TK;TV;>;\n\n        public static <K extends java.lang.Object, V extends java.lang.Object> java.util.Map<K, V> newHashMap(java.util.Map<K, V>);\n        */\n        if !signature.generics.is_empty() {\n            retype.push_str(\"<\");\n\n            let lst: Vec<String> = signature\n                .generics\n                .iter()\n                .map(|(holder, t)| {\n                    let mut s = String::from_utf8_lossy(holder.as_slice()).to_string();\n                    s.push_str(\" extends \");\n                    let t = t.into_string();\n                    s.push_str(&t);\n                    s\n                })\n                .collect();\n            let s = lst.join(\", \");\n\n            retype.push_str(&s);\n            retype.push_str(\"> \");\n        }\n\n        let s = signature.retype.into_string();\n        retype.push_str(&s);\n\n        retype\n    }\n\n    fn args(&self) -> Vec<String> {\n        let signature = self.method_signature();\n        signature.args.iter().map(|it| it.into_string()).collect()\n    }\n\n    fn code(&self) -> CodeSerde {\n        match self.method.get_code() {\n            Some(code) => {\n                let t = CodeTranslator {\n                    cf: self.cf,\n                    code: &code,\n                };\n                let codes = t.get();\n                let args_size = if self.method.acc_flags.is_static() {\n                    self.args().len()\n                } else {\n                    self.args().len() + 1\n                };\n                CodeSerde {\n                    max_stack: code.max_stack,\n                    max_locals: code.max_locals,\n                    args_size,\n                    codes,\n                    enable_verbose: false,\n                }\n            }\n            None => Default::default(),\n        }\n    }\n\n    fn throws(&self) -> Option<String> {\n        self.method.get_throws().map(|v| {\n            let exs: Vec<String> = v\n                .iter()\n                .map(|it| {\n                    let name = constant_pool::get_class_name(&self.cf.cp, *it as usize).unwrap();\n                    String::from_utf8_lossy(name.as_slice()).replace(\"/\", \".\")\n                })\n                .collect();\n\n            exs.join(\", \")\n        })\n    }\n\n    fn ex_table(&self) -> Vec<String> {\n        let ext = self.method.get_ex_table();\n        match ext {\n            Some(ext) => {\n                let mut table = Vec::with_capacity(1 + ext.len());\n                let v = format!(\"{:5} {:>5} {:6} {:4}\", \"from\", \"to \", \"target\", \"type\");\n                table.push(v);\n\n                for ex in ext.iter() {\n                    let t = if ex.is_finally() {\n                        \"any\".to_string()\n                    } else {\n                        let name =\n                            constant_pool::get_class_name(&self.cf.cp, ex.catch_type as usize)\n                                .unwrap();\n                        format!(\"Class {}\", String::from_utf8_lossy(name.as_slice()))\n                    };\n                    let v = format!(\n                        \"{:>5} {:>5} {:>5}   {}\",\n                        ex.start_pc, ex.end_pc, ex.handler_pc, t\n                    );\n                    table.push(v)\n                }\n\n                table\n            }\n            _ => vec![],\n        }\n    }\n\n    fn stack_map_table(&self) -> Vec<StackMapTableTranslation> {\n        match self.method.get_stack_map_table() {\n            Some(t) => {\n                let mut table = Vec::with_capacity(t.len());\n\n                for it in t.iter() {\n                    match it {\n                        StackMapFrame::Append {\n                            tag,\n                            offset_delta,\n                            locals,\n                        } => {\n                            let infos = self.build_verification_type_infos(locals);\n                            let items = vec![\n                                format!(\"offset_delta = {}\", *offset_delta),\n                                format!(\"locals = [ {} ]\", infos.join(\", \")),\n                            ];\n\n                            table.push(StackMapTableTranslation {\n                                tag: *tag,\n                                comment: \"/* append */\",\n                                items,\n                            });\n                        }\n                        StackMapFrame::Same {\n                            tag,\n                            offset_delta: _,\n                        } => {\n                            table.push(StackMapTableTranslation {\n                                tag: *tag,\n                                comment: \"/* same */\",\n                                items: vec![],\n                            });\n                        }\n                        StackMapFrame::SameLocals1StackItem {\n                            tag,\n                            offset_delta: _,\n                            stack,\n                        } => {\n                            let stack = stack.to_vec();\n                            let infos = self.build_verification_type_infos(&stack);\n                            table.push(StackMapTableTranslation {\n                                tag: *tag,\n                                comment: \"/* same_locals_1_stack_item */\",\n                                items: vec![format!(\"stack = [ {} ]\", infos.join(\", \"))],\n                            });\n                        }\n                        StackMapFrame::SameLocals1StackItemExtended {\n                            tag,\n                            offset_delta: _,\n                            stack: _,\n                        } => {\n                            trace!(\"todo: StackMapFrame::SameLocals1StackItemExtended\");\n                            table.push(StackMapTableTranslation {\n                                tag: *tag,\n                                comment: \"/* todo: SameLocals1StackItemExtended */\",\n                                items: vec![],\n                            });\n                        }\n                        StackMapFrame::Chop { tag, offset_delta } => {\n                            table.push(StackMapTableTranslation {\n                                tag: *tag,\n                                comment: \"/* chop */\",\n                                items: vec![format!(\"offset_delta = {}\", *offset_delta)],\n                            });\n                        }\n                        StackMapFrame::SameExtended {\n                            tag,\n                            offset_delta: _,\n                        } => {\n                            trace!(\"todo: StackMapFrame::SameExtended\");\n                            table.push(StackMapTableTranslation {\n                                tag: *tag,\n                                comment: \"/* todo: SameExtended */\",\n                                items: vec![],\n                            });\n                        }\n                        StackMapFrame::Full {\n                            tag,\n                            offset_delta,\n                            locals,\n                            stack,\n                        } => {\n                            let locals = self.build_verification_type_infos(locals);\n                            let stack = self.build_verification_type_infos(stack);\n                            let mut items = Vec::with_capacity(3);\n                            items.push(format!(\"offset_delta = {}\", *offset_delta));\n                            items.push(format!(\"locals = [ {} ]\", locals.join(\", \")));\n                            items.push(format!(\"stack = [ {} ]\", stack.join(\", \")));\n                            table.push(StackMapTableTranslation {\n                                tag: *tag,\n                                comment: \"/* full_frame */\",\n                                items,\n                            });\n                        }\n                        StackMapFrame::Reserved(_) => {}\n                    }\n                }\n\n                table\n            }\n            None => vec![],\n        }\n    }\n\n    fn local_variable_table(&self) -> Vec<String> {\n        match self.method.get_local_variable_table() {\n            Some(vars) => self.build_variable_table(&vars),\n            None => vec![],\n        }\n    }\n\n    fn local_variable_type_table(&self) -> Vec<String> {\n        match self.method.get_local_variable_type_table() {\n            Some(vars) => self.build_variable_table(&vars),\n            None => vec![],\n        }\n    }\n}\n\nimpl<'a> Translator<'a> {\n    fn build_verification_type_infos(&self, locals: &Vec<VerificationTypeInfo>) -> Vec<String> {\n        let mut infos = Vec::with_capacity(locals.len());\n\n        for it in locals.iter() {\n            match it {\n                VerificationTypeInfo::Float => {\n                    infos.push(\"float\".to_string());\n                }\n                VerificationTypeInfo::Top => {\n                    infos.push(\"top\".to_string());\n                }\n                VerificationTypeInfo::Integer => {\n                    infos.push(\"int\".to_string());\n                }\n                VerificationTypeInfo::Long => {\n                    infos.push(\"long\".to_string());\n                }\n                VerificationTypeInfo::Double => {\n                    infos.push(\"double\".to_string());\n                }\n                VerificationTypeInfo::Null => {\n                    infos.push(\"null\".to_string());\n                }\n                VerificationTypeInfo::UninitializedThis => {\n                    infos.push(\"UninitializedThis\".to_string());\n                }\n                VerificationTypeInfo::Object { cpool_index } => {\n                    let name =\n                        constant_pool::get_class_name(&self.cf.cp, *cpool_index as usize).unwrap();\n                    let name = String::from_utf8_lossy(name.as_slice());\n                    let v = if name.starts_with(\"[\") {\n                        format!(\"class \\\"{}\\\"\", name)\n                    } else {\n                        format!(\"class {}\", name)\n                    };\n                    infos.push(v);\n                }\n                VerificationTypeInfo::Uninitialized { offset: _ } => {\n                    infos.push(\"Uninitialized\".to_string());\n                }\n            }\n        }\n\n        infos\n    }\n\n    fn build_variable_table(&self, local_vars: &Vec<LocalVariable>) -> Vec<String> {\n        let mut table = Vec::with_capacity(1 + local_vars.len());\n        table.push(format!(\n            \"{:5}  {:6}  {:4}  {:>5}  {}\",\n            \"Start\", \"Length\", \"Slot\", \"Name\", \"Signature\"\n        ));\n        for it in local_vars.iter() {\n            let name = constant_pool::get_utf8(&self.cf.cp, it.name_index as usize).unwrap();\n            let name = String::from_utf8_lossy(name.as_slice());\n            let signature =\n                constant_pool::get_utf8(&self.cf.cp, it.signature_index as usize).unwrap();\n            let signature = String::from_utf8_lossy(signature.as_slice());\n            let v = format!(\n                \"{:>5}  {:>6}  {:>4}  {:>5}  {}\",\n                it.start_pc, it.length, it.index, name, signature\n            );\n            table.push(v);\n        }\n\n        table\n    }\n\n    //Attribute::Signature contains signature details\n    //such as, generics info; but constant pool only contains container info\n    //\n    // Attribute::Signature\n    //()Ljava/util/List<Lorg/testng/ITestNGListener;>;\n    //\n    //constant pool\n    //()Ljava/util/List;\n    fn attr_signature(&self) -> Option<(usize, BytesRef)> {\n        for it in self.method.attrs.iter() {\n            match it {\n                classfile::attributes::Type::Signature { signature_index } => {\n                    let signature_index = *signature_index as usize;\n                    let v = constant_pool::get_utf8(&self.cf.cp, signature_index).unwrap();\n                    return Some((signature_index, v));\n                }\n                _ => (),\n            }\n        }\n\n        None\n    }\n\n    fn descriptor(&self) -> BytesRef {\n        constant_pool::get_utf8(&self.cf.cp, self.method.desc_index as usize).unwrap()\n    }\n\n    fn method_signature(&self) -> MethodSignature {\n        let desc = match self.attr_signature() {\n            Some((_, v)) => v,\n            None => self.descriptor(),\n        };\n        MethodSignature::new(desc.as_slice())\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/trans/mod.rs",
    "content": "use classfile::{ClassFile, SignatureType};\n\nmod access_flag;\nmod class_file;\nmod code;\nmod constant_pool_trans;\nmod field;\nmod instruction;\nmod method;\nmod signature_type;\n\npub use self::access_flag::AccessFlagHelper;\npub use self::access_flag::Translator as AccessFlagsTranslator;\npub use self::class_file::Translator as ClassFileTranslator;\npub use self::code::Translator as CodeTranslator;\npub use self::constant_pool_trans::Translator as ConstantPoolTranslator;\npub use self::field::FieldTranslation;\npub use self::field::Translator as FieldTranslator;\npub use self::method::MethodTranslation;\npub use self::method::Translator as MethodTranslator;\npub use self::signature_type::Translator as SignatureTypeTranslator;\n\npub fn class_source_file(cf: &ClassFile) -> String {\n    let x = ClassFileTranslator::new(cf);\n    x.source_file()\n}\n\npub fn class_this_class(cf: &ClassFile) -> String {\n    let x = ClassFileTranslator::new(cf);\n    x.this_class()\n}\n\npub fn class_super_class(cf: &ClassFile) -> String {\n    let x = ClassFileTranslator::new(cf);\n    x.super_class()\n}\n\npub fn class_access_flags(cf: &ClassFile) -> String {\n    let x = ClassFileTranslator::new(cf);\n    x.access_flags()\n}\n\npub fn class_access_flags_name(cf: &ClassFile) -> String {\n    let x = ClassFileTranslator::new(cf);\n    x.access_flags_name()\n}\n\npub fn class_signature_raw(cf: &ClassFile) -> Option<String> {\n    let x = ClassFileTranslator::new(cf);\n    x.signature_raw()\n}\n\npub fn class_signature(cf: &ClassFile) -> Option<Vec<SignatureType>> {\n    let x = ClassFileTranslator::new(cf);\n    x.signature()\n}\n\npub fn class_fields(cf: &ClassFile, flags: u16) -> Vec<FieldTranslation> {\n    let x = ClassFileTranslator::new(cf);\n    x.fields(flags)\n}\n\npub fn class_methods(\n    cf: &ClassFile,\n    with_line_num: bool,\n    with_code: bool,\n    flags: u16,\n) -> Vec<MethodTranslation> {\n    let x = ClassFileTranslator::new(cf);\n    x.methods(with_line_num, with_code, flags)\n}\n\npub fn class_parent_interfaces(cf: &ClassFile) -> Vec<String> {\n    let x = ClassFileTranslator::new(cf);\n    x.parent_interfaces()\n}\n\npub fn class_constant_pool(cf: &ClassFile) -> Vec<String> {\n    let x = ConstantPoolTranslator { cf };\n    x.get()\n}\n\npub fn class_inner_classes(cf: &ClassFile) -> Vec<String> {\n    let x = ClassFileTranslator::new(cf);\n    x.inner_classes()\n}\n"
  },
  {
    "path": "tools/javap/src/trans/signature_type.rs",
    "content": "use classfile::SignatureType;\n\npub trait Translator {\n    fn into_string(&self) -> String;\n}\n\nimpl Translator for SignatureType {\n    fn into_string(&self) -> String {\n        match self {\n            SignatureType::Int => \"int\".into(),\n            SignatureType::Byte => \"byte\".into(),\n            SignatureType::Char => \"char\".into(),\n            SignatureType::Double => \"double\".into(),\n            SignatureType::Float => \"float\".into(),\n            SignatureType::Long => \"long\".into(),\n            SignatureType::Object(desc, generics, prefix) => match generics {\n                Some(generics) => {\n                    let generics: Vec<String> =\n                        generics.iter().map(|it| it.into_string()).collect();\n                    let generics = generics.join(\", \");\n\n                    let mut s = to_java_style(&desc);\n                    s.push('<');\n                    match prefix {\n                        Some(b'+') => s.push_str(\"? extends \"),\n                        _ => (),\n                    }\n                    s.push_str(&generics);\n                    s.push('>');\n                    s\n                }\n                None => to_java_style(&desc),\n            },\n            SignatureType::Short => \"short\".into(),\n            SignatureType::Boolean => \"boolean\".into(),\n            SignatureType::Array(desc) => to_java_style(&desc),\n            SignatureType::Void => \"void\".into(),\n        }\n    }\n}\n\nfn to_java_style(desc: &[u8]) -> String {\n    //calc array dimensions\n    let mut i = 0;\n    while desc[i] == b'[' {\n        i += 1;\n    }\n    let ary_size = i;\n\n    let mut name = if desc[i] == b'L' || desc[i] == b'T' {\n        let desc = &desc[(i + 1)..(desc.len() - 1)];\n        String::from_utf8_lossy(desc).replace(\"/\", \".\")\n    } else {\n        match desc[i] {\n            b'B' => \"byte\".into(),\n            b'C' => \"char\".into(),\n            b'D' => \"double\".into(),\n            b'F' => \"float\".into(),\n            b'I' => \"int\".into(),\n            b'J' => \"long\".into(),\n            b'S' => \"short\".into(),\n            b'Z' => \"boolean\".into(),\n            _ => unreachable!(),\n        }\n    };\n\n    for _ in 0..ary_size {\n        name.push_str(\"[]\");\n    }\n\n    name\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn t_parse() {\n        let tests = vec![\n            (\"Ljava/lang/Object;\", \"java.lang.Object\"),\n            (\"[Ljava/lang/Object;\", \"java.lang.Object[]\"),\n            (\"[[Ljava/lang/Object;\", \"java.lang.Object[][]\"),\n            (\"[B\", \"byte[]\"),\n            (\"[C\", \"char[]\"),\n            (\"[D\", \"double[]\"),\n            (\"[F\", \"float[]\"),\n            (\"[J\", \"long[]\"),\n            (\"[S\", \"short[]\"),\n            (\"[Z\", \"boolean[]\"),\n        ];\n\n        for it in tests.iter() {\n            assert_eq!(to_java_style(it.0.as_bytes()), it.1);\n        }\n    }\n}\n"
  },
  {
    "path": "tools/javap/src/util/mod.rs",
    "content": "mod sys;\n\npub use self::sys::*;\n\npub const JAR_FILE_PREFIX: &str = \"jar:file:\";\n"
  },
  {
    "path": "tools/javap/src/util/sys.rs",
    "content": "#![allow(unused)]\n\nuse std::time::SystemTime;\nuse time::OffsetDateTime;\n\npub const FILE_SEP: &str = platform::FILE_SEP;\npub const PATH_SEP: &str = platform::PATH_SEP;\npub const LINE_SEP: &str = \"\\n\";\nconst LAST_MODIFIED_FORMAT: &str = \"%b %-d, %Y\";\n\n#[cfg(unix)]\nmod platform {\n    pub const FILE_SEP: &str = \"/\";\n    pub const PATH_SEP: &str = \":\";\n}\n\n#[cfg(windows)]\nmod platform {\n    pub const FILE_SEP: &str = \"\\\\\";\n    pub const PATH_SEP: &str = \";\";\n}\n\npub fn to_abs_path(src: &str) -> String {\n    let src = std::path::PathBuf::from(src);\n    match std::fs::canonicalize(&src) {\n        Ok(pb) => pb.to_string_lossy().to_string(),\n        Err(_) => String::new(),\n    }\n}\n\npub fn md5_checksum(data: &[u8]) -> String {\n    let digest = md5::compute(data);\n    format!(\"{:x}\", digest)\n}\n\npub fn format_time1(t: SystemTime) -> String {\n    match t.duration_since(std::time::SystemTime::UNIX_EPOCH) {\n        Ok(t) => {\n            let odt = OffsetDateTime::from_unix_timestamp(t.as_secs() as i64);\n            odt.format(LAST_MODIFIED_FORMAT)\n        }\n        Err(_) => \"\".to_string(),\n    }\n}\n\npub fn format_time2(sec: i64) -> String {\n    let odt = OffsetDateTime::from_unix_timestamp(sec);\n    odt.format(LAST_MODIFIED_FORMAT)\n}\n"
  },
  {
    "path": "tools/javap/test/AbstractGraphicObject.java",
    "content": "abstract class AbstractGraphicObject {\n   // declare fields\n   // declare nonabstract methods\n   abstract void draw();\n}\n"
  },
  {
    "path": "tools/javap/test/EnumMobile.java",
    "content": "import java.lang.*;\n\n// enum showing Mobile prices\npublic enum EnumMobile {\n   Samsung(400), Nokia(250);\n  \n   int price;\n   EnumMobile(int p) {\n      price = p;\n   }\n   int showPrice() {\n      return price;\n   } \n}\n"
  },
  {
    "path": "tools/javap/test/Football.java",
    "content": "public interface Football extends Sports {\n   public void homeTeamScored(int points);\n   public void visitingTeamScored(int points);\n   public void endOfQuarter(int quarter);\n}\n"
  },
  {
    "path": "tools/javap/test/HelloWorld.java",
    "content": "public final class HelloWorld\n{\n    float v_float = 2.5f;\n    double v_double = 2.0;\n    int v_int = 100;\n    long v_long = 20000l;\n\n    int count;\n    String name;\n\n    public HelloWorld() {\n\n    }\n\n    public static void main(String[] args)\n    {\n        System.out.println(\"Hello, World!\");\n\n        System.out.println(\"args: \" + args);\n        for (String s: args) {\n            System.out.println(\"arg: \" + s);\n        }\n\n        if (args != null) {\n            for (int i = 0; i < args.length; i++) {\n                System.out.println(\"arg[\" + i + \"] = \" + args[i]);\n            }\n        }\n    }\n\n    private void private_method() {\n        System.out.println(\"I'm private method\");\n    }\n\n    protected void protected_method() {\n        System.out.println(\"I'm protected method\");\n    }\n\n    void package_method() {\n        System.out.println(\"I'm package method\");\n    }\n\n    public void public_method() {\n        System.out.println(\"I'm public method\");\n    }\n} \n"
  },
  {
    "path": "tools/javap/test/Hockey.java",
    "content": "public interface Hockey extends Sports {\n   public void homeGoalScored();\n   public void visitingGoalScored();\n   public void endOfPeriod(int period);\n   public void overtimePeriod(int ot);\n}\n"
  },
  {
    "path": "tools/javap/test/Interface1.java",
    "content": "import java.io.InputStream;\n\npublic interface Interface1 {\n\n        double E = 2.718282;\n\n        void print(byte[] b1, Object o1);\n        InputStream get_is();\n        Object[][] get_ary1();\n        int[][] get_ary2();\n   }\n"
  },
  {
    "path": "tools/javap/test/Sports.java",
    "content": "public interface Sports {\n   public void setHomeTeam(String name);\n   public void setVisitingTeam(String name);\n}\n"
  },
  {
    "path": "tools/misc/instruction.py",
    "content": "#!/usr/bin/env python3\n\n# -*- coding: utf-8 -*-\nimport sys\n\n# (name, 1 + encoded_value_length, bytecode value)\n# encoded_value to calc index in constant pool\ninstructions = [\n    (\"aaload\", 1, 50),\n    (\"aastore\", 1, 83),\n    (\"aconst_null\", 1, 1),\n    (\"aload\", 2, 25),\n    (\"aload_0\", 1, 42),\n    (\"aload_1\", 1, 43),\n    (\"aload_2\", 1, 44),\n    (\"aload_3\", 1, 45),\n    (\"anewarray\", 3, 189),\n    (\"areturn\", 1, 176),\n    (\"arraylength\", 1, 190),\n    (\"astore\", 2, 58),\n    (\"astore_0\", 1, 75),\n    (\"astore_1\", 1, 76),\n    (\"astore_2\", 1, 77),\n    (\"astore_3\", 1, 78),\n    (\"athrow\", 1, 191),\n    (\"baload\", 1, 51),\n    (\"bastore\", 1, 84),\n    (\"bipush\", 2, 16),\n    (\"caload\", 1, 52),\n    (\"castore\", 1, 85),\n    (\"checkcast\", 3, 192),\n    (\"d2f\", 1, 144),\n    (\"d2i\", 1, 142),\n    (\"d2l\", 1, 143),\n    (\"dadd\", 1, 99),\n    (\"daload\", 2, 49),\n    (\"dastore\", 1, 82),\n    (\"dcmpg\", 1, 152),\n    (\"dcmpl\", 1, 151),\n    (\"dconst_0\", 1, 14),\n    (\"dconst_1\", 1, 15),\n    (\"ddiv\", 1, 111),\n    (\"dload\", 2, 24),\n    (\"dload_0\", 1, 38),\n    (\"dload_1\", 1, 39),\n    (\"dload_2\", 1, 40),\n    (\"dload_3\", 1, 41),\n    (\"dmul\", 1, 107),\n    (\"dneg\", 1, 119),\n    (\"drem\", 1, 115),\n    (\"dreturn\", 1, 175),\n    (\"dstore\", 2, 57),\n    (\"dstore_0\", 1, 71),\n    (\"dstore_1\", 1, 72),\n    (\"dstore_2\", 1, 73),\n    (\"dstore_3\", 1, 74),\n    (\"dsub\", 1, 103),\n    (\"dup\", 1, 89),\n    (\"dup2\", 1, 92),\n    (\"dup2_x1\", 1, 93),\n    (\"dup2_x2\", 1, 94),\n    (\"dup_x1\", 1, 90),\n    (\"dup_x2\", 1, 91),\n    (\"f2d\", 1, 141),\n    (\"f2i\", 1, 139),\n    (\"f2l\", 1, 140),\n    (\"fadd\", 1, 98),\n    (\"faload\", 1, 48),\n    (\"fastore\", 1, 81),\n    (\"fcmpg\", 1, 150),\n    (\"fcmpl\", 1, 149),\n    (\"fconst_0\", 1, 11),\n    (\"fconst_1\", 1, 12),\n    (\"fconst_2\", 1, 13),\n    (\"fdiv\", 1, 110),\n    (\"fload\", 2, 23),\n    (\"fload_0\", 1, 34),\n    (\"fload_1\", 1, 35),\n    (\"fload_2\", 1, 36),\n    (\"fload_3\", 1, 37),\n    (\"fmul\", 1, 106),\n    (\"fneg\", 1, 118),\n    (\"frem\", 1, 114),\n    (\"freturn\", 1, 174),\n    (\"fstore\", 2, 56),\n    (\"fstore_0\", 1, 67),\n    (\"fstore_1\", 1, 68),\n    (\"fstore_2\", 1, 69),\n    (\"fstore_3\", 1, 70),\n    (\"fsub\", 1, 102),\n    (\"getfield\", 3, 180),\n    (\"getstatic\", 3, 178),\n    (\"goto\", 3, 167),\n    (\"goto_w\", 5, 200),\n    (\"i2b\", 1, 145),\n    (\"i2c\", 1, 146),\n    (\"i2d\", 1, 135),\n    (\"i2f\", 1, 134),\n    (\"i2l\", 1, 133),\n    (\"i2s\", 1, 147),\n    (\"iadd\", 1, 96),\n    (\"iaload\", 1, 46),\n    (\"iand\", 1, 126),\n    (\"iastore\", 1, 79),\n    (\"iconst_0\", 1, 3),\n    (\"iconst_1\", 1, 4),\n    (\"iconst_2\", 1, 5),\n    (\"iconst_3\", 1, 6),\n(\"iconst_4\", 1, 7),\n(\"iconst_5\", 1, 8),\n(\"iconst_m1\", 1, 2),\n(\"idiv\", 1, 108),\n(\"if_acmpeq\", 3, 165),\n(\"if_acmpne\", 3, 166),\n(\"if_icmpeq\", 3, 159),\n(\"if_icmpge\", 3, 162),\n(\"if_icmpgt\", 3, 163),\n(\"if_icmple\", 3, 164),\n(\"if_icmplt\", 3, 161),\n(\"if_icmpne\", 3, 160),\n(\"ifeq\", 3, 153),\n(\"ifge\", 3, 156),\n(\"ifgt\", 3, 157),\n(\"ifle\", 3, 158),\n(\"iflt\", 3, 155),\n(\"ifne\", 3, 154),\n(\"ifnonnull\", 3, 199),\n(\"ifnull\", 3, 198),\n(\"iinc\", 3, 132),\n(\"iload\", 2, 21),\n(\"iload_0\", 1, 26),\n(\"iload_1\", 1, 27),\n(\"iload_2\", 1, 28),\n(\"iload_3\", 1, 29),\n(\"imul\", 1, 104),\n(\"ineg\", 1, 116),\n(\"instanceof\", 3, 193),\n(\"invokedynamic\", 5, 186),\n(\"invokeinterface\", 5, 185),\n(\"invokespecial\", 3, 183),\n(\"invokestatic\", 3, 184),\n(\"invokevirtual\", 3, 182),\n(\"ior\", 1, 128),\n(\"irem\", 1, 112),\n(\"ireturn\", 1, 172),\n(\"ishl\", 1, 120),\n(\"ishr\", 1, 122),\n(\"istore\", 2, 54),\n(\"istore_0\", 1, 59),\n(\"istore_1\", 1, 60),\n(\"istore_2\", 1, 61),\n(\"istore_3\", 1, 62),\n(\"isub\", 1, 100),\n(\"iushr\", 1, 124),\n(\"ixor\", 1, 130),\n(\"jsr\", 3, 168),\n(\"jsr_w\", 5, 201),\n(\"l2d\", 1, 138),\n(\"l2f\", 1, 137),\n(\"l2i\", 1, 136),\n(\"ladd\", 1, 97),\n(\"laload\", 1, 47),\n(\"land\", 1, 127),\n(\"lastore\", 1, 80),\n(\"lcmp\", 1, 148),\n(\"lconst_0\", 1, 9),\n(\"lconst_1\", 1, 10),\n(\"ldc\", 2, 18),\n(\"ldc2_w\", 3, 20),\n(\"ldc_w\", 3, 19),\n(\"ldiv\", 1, 109),\n(\"lload\", 2, 22),\n(\"lload_0\", 1, 30),\n(\"lload_1\", 1, 31),\n(\"lload_2\", 1, 32),\n(\"lload_3\", 1, 33),\n(\"lmul\", 1, 105),\n(\"lneg\", 1, 117),\n(\"lookupswitch\", \"variable-length instruction\", 171),\n(\"lor\", 1, 129),\n(\"lrem\", 1, 113),\n(\"lreturn\", 1, 173),\n(\"lshl\", 1, 121),\n(\"lshr\", 1, 123),\n(\"lstore\", 2, 55),\n(\"lstore_0\", 1, 63),\n(\"lstore_1\", 1, 64),\n(\"lstore_2\", 1, 65),\n(\"lstore_3\", 1, 66),\n(\"lsub\", 1, 101),\n(\"lushr\", 1, 125),\n(\"lxor\", 1, 131),\n(\"monitorenter\", 1, 194),\n(\"monitorexit\", 1, 195),\n(\"multianewarray\", 4, 197),\n(\"new\", 3, 187),\n(\"newarray\", 2, 188),\n(\"nop\", 1, 0),\n(\"pop\", 1, 87),\n(\"pop2\", 1, 88),\n(\"putfield\", 3, 181),\n(\"putstatic\", 3, 179),\n(\"ret\", 2, 169),\n(\"return_void\", 1, 177),\n(\"saload\", 1, 53),\n(\"sastore\", 1, 86),\n(\"sipush\", 3, 17),\n(\"swap\", 1, 95),\n(\"tableswitch\", \"variable-length instruction\", 170),\n(\"wide\", 1, 196),\n]\n\ndef create_get_instructions(ary):\n    ary = sorted(ary, key=lambda it: it[2])\n    with open(\"mod.get_instructions\", \"w\") as f:\n        f.write(\"pub fn get_instructions() -> Vec<Box<dyn Instruction>> {\\n\")\n        f.write(\"\\tvec![\\n\")\n        for it in ary:\n            name = it[0]\n            f.write(\"\\t\\tBox::new(\" + name.title() + \"),\\n\")\n        f.write(\"\\t]\\n\")\n        f.write(\"}\\n\")\n\n\ndef create_uses(ary):\n    with open(\"mod.uses\", \"w\") as f:\n        for it in ary:\n            name = it[0]\n            f.write(\"mod \" + name + \";\\n\")\n        f.write(\"\\n\")\n        for it in ary:\n            name = it[0]\n            f.write(\"use \" + name + \"::\" + name.title() + \";\\n\")\n\ndef create_mod(instruction):\n    (name, step, _) = instruction\n    with open(name + \".rs\", \"w\") as f:\n        f.write(\"#![allow(non_camel_case_types)]\\n\")\n        f.write(\"use classfile::OpCode;\\n\")\n        f.write(\"use super::{Instruction, InstructionInfo};\\n\")\n        f.write(\"\\n\")\n        f.write(\"pub struct \" + name.title() + \";\\n\")\n        f.write(\"\\n\")\n        f.write(\"impl Instruction for \" + name.title() + \" {\\n\")\n        f.write(\"   fn run(&self, codes: &[u8], pc: usize) -> (InstructionInfo, usize) {\\n\")\n        f.write(\"       let info = InstructionInfo {\\n\")\n        f.write(\"           op_code: OpCode::\" + name + \",\\n\")\n        if name in [\"instanceof\", \"multianewarray\", \"invokevirtual\", \"anewarray\", \"checkcast\", \n            \"putfield\", \"getfield\", \"getstatic\", \"invokespecial\", \"ldc2_w\", \"invokeinterface\", \n            \"new\", \"invokestatic\", \"ldc_w\", \"putstatic\", \"invokedynamic\"]:\n            f.write(\"           icp: self.calc_cp_index_u16(codes, pc)\\n\")\n        else:\n            f.write(\"           icp: 0\\n\")\n        f.write(\"       };\\n\")\n        f.write(\"\\n\")\n        if name in [\"lookupswitch\", \"tableswitch\", \"wide\"]:\n            f.write(\"\\tunimplemented!(\\\"\" + str(step) + \"\\\")\")\n        else:\n            f.write(\"       (info, pc + \" + str(step) + \")\\n\")\n        f.write(\"   }\\n\")\n        f.write(\"}\")\n\nif __name__ == '__main__':\n    # create_get_instructions(instructions)\n    # create_uses(instructions)\n    for it in instructions:\n        create_mod(it)\n\n\n\n"
  },
  {
    "path": "tools/misc/native.py",
    "content": "#!/usr/bin/env python3\n\n# -*- coding: utf-8 -*-\nimport sys\n\n\nif __name__ == '__main__':\n\tdesc = sys.argv[1]\n\t[package, name, signature] = desc.split(\":\")\n\n\tmod = package.replace(\"/\", \"_\")\n\tprint(mod)\n\tprint()\n\n\tprint(\"mod \" + mod + \";\")\n\tprint()\n\n\tprint(\"(\\\"\" + package + \"\\\", \" + mod + \"::get_native_methods()),\")\n\tprint()\n\n\tprint(\"#![allow(non_snake_case)]\")\n\tprint()\n\tprint(\"use crate::native::{new_fn, JNIEnv, JNINativeMethod, JNIResult};\")\n\tprint(\"use crate::oop::{self, Oop};\")\n\tprint()\n\tprint(\"pub fn get_native_methods() -> Vec<JNINativeMethod> {\")\n\tprint(\"\\tvec![\")\n\tprint()\n\tprint(\"\\t]\")\n\tprint(\"}\")\n\tprint()\n\n\tprint(\"new_fn(\\\"\" + name + \"\\\", \" + \"\\\"\" + signature + \"\\\", \" + \"Box::new(jvm_\" + name + \")),\")\n\tprint()\n\n\tprint(\"fn jvm_\" + name + \"(_env: JNIEnv, _args: &Vec<Oop>) -> JNIResult {\")\n\tprint(\"\\tOk(None)\")\n\tprint(\"}\")\n"
  }
]