├── .gitignore ├── LICENSE ├── README.md ├── Zvm.py ├── base ├── __init__.py ├── jvm_config.py ├── stack.py └── utils │ ├── __init__.py │ ├── common_utils.py │ ├── error_handler.py │ └── print_utils.py ├── instruction ├── __init__.py └── instruction.py ├── interpreter ├── __init__.py ├── code_parser.py └── interpreter.py ├── java_class ├── __init__.py ├── class_file.py └── class_parser.py ├── jgc ├── __init__.py └── gc.py ├── jthread ├── __init__.py └── jthread.py ├── note.md ├── path_import.py ├── res ├── pic1.png └── pic2.png ├── runtime ├── __init__.py ├── heap.py ├── java_heap.py ├── jclass.py ├── jobject.py └── thread.py └── test ├── Hello$1.class ├── Hello$NOT.class ├── Hello$T.class ├── Hello$T1.class ├── Hello$T2.class ├── Hello$TestException.class ├── Hello.class ├── Hello.java ├── Main.class ├── Main.java ├── java ├── io │ ├── PrintStream.class │ └── PrintStream.java └── lang │ ├── Exception.class │ ├── Exception.java │ ├── Object.class │ ├── Object.java │ ├── RuntimeException.class │ ├── RuntimeException.java │ ├── System.class │ ├── System.java │ ├── Thread.class │ ├── Thread.java │ ├── Throwable.class │ └── Throwable.java └── test.py /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | /*/*.pyc 3 | /*/__pycache__ 4 | *.pyc 5 | .DS_Store 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Zvm 2 | 3 | #### 简介 4 | 一款 python 实现的 "超轻量级" jvm 的实现 (其实就是只实现了主要功能) 5 | "完美"运行各种姿势的 HelloWorld 6 | 7 | #### 如何使用 8 | 方法一: 9 | 1. 在 test 目录下新建 .java 文件,可参考 Main.java (因为重写了一些 jdk,所以需要在这个目录下编译,为什么重写 jdk,因为 jdk 中很多 native 方法,这次又没有实现 native 方法,so sad) 10 | 2. javac 编译 11 | 3. 在 Zvm 目录下运行 python3 Zvm.py test/Main 12 | 13 | 方法二: 14 | 直接工程导入 pycharm 运行 test.py 吧 15 | 16 | #### 主要实现部分 17 | class 文件解析 18 | 类加载 19 | 运行时数据区 20 | 指令解释器 21 | 基本指令集 (总共 205 条,实现了估计 190 多条吧) 22 | 简易 gc 23 | 简易线程 24 | 简易 jdk 库 25 | 26 | #### 可用功能 27 | 基本运算 (加减乘除与或位移...) 28 | 输出 29 | 多线程运算 (但是没有加同步) 30 | 类加载,继承,多态 31 | 数组操作 (只支持一维数组) 32 | gc (模拟 gc) 33 | 异常处理 34 | 35 | #### TODO 36 | 代码整理 37 | 方法分派采用 vtable 38 | interface 39 | 多维数组 40 | native 方法 41 | 方法,变量验证 42 | class_loader 读取 jar zip 文件 43 | 44 | #### 参考资料 45 | 46 | <揭秘 java 虚拟机> 47 | 48 | <自己动手写 java 虚拟机> 49 | ... 50 | 51 | #### 运行展示 52 | ![run1](./res/pic1.png) 53 | ![run2](./res/pic2.png) 54 | 55 | #### LAST 56 | enjoy it 57 | -------------------------------------------------------------------------------- /Zvm.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | 3 | import path_import 4 | import sys 5 | 6 | from runtime.jclass import ClassLoader 7 | from interpreter import interpreter 8 | 9 | 10 | def parse_params(): 11 | args = sys.argv 12 | if len(args) <= 1: 13 | print('use: python Zvm.py xx[.class]') 14 | print('eg: python Zvm.py main') 15 | print('eg: python Zvm.py main.class') 16 | return None 17 | name = sys.argv[1] 18 | if name.endswith('.class'): 19 | name = name[:name.find('.class')] 20 | return name 21 | 22 | 23 | def main(): 24 | class_file = parse_params() 25 | if class_file is None: 26 | return 27 | loader = ClassLoader() 28 | j_class = loader.load_class(class_file) 29 | print(j_class) 30 | method = j_class.get_main_method() 31 | interpreter.Interpreter.exec_method(method) 32 | 33 | 34 | if __name__ == '__main__': 35 | main() 36 | -------------------------------------------------------------------------------- /base/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/5A59/Zvm/d093558c567488472252a4f6f87cecbc0ec2bd38/base/__init__.py -------------------------------------------------------------------------------- /base/jvm_config.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | 3 | import os 4 | 5 | log_jvm_status = False 6 | # log_jvm_status = True 7 | 8 | print_in_real_time = True 9 | 10 | cur_path = os.getcwd() 11 | jdk_path = [cur_path + '/', cur_path + '/test/'] 12 | 13 | heap_size = 11 # 这个是按 ref 个数模拟的 gc,不是真实的 size 14 | -------------------------------------------------------------------------------- /base/stack.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | 3 | from base.utils.print_utils import print_jvm_status 4 | 5 | 6 | class Stack(object): 7 | def __init__(self): 8 | self.__items = [] 9 | 10 | def items(self): 11 | return self.__items 12 | 13 | def get_val_at(self, index): 14 | return self.__items[len(self.__items) - index - 1] 15 | 16 | def print_state(self): 17 | print_jvm_status(self.__items) 18 | 19 | def push(self, data): 20 | self.__items.append(data) 21 | 22 | def size(self): 23 | return len(self.__items) 24 | 25 | def peek(self): 26 | return self.__items[self.size() - 1] 27 | 28 | def pop(self): 29 | return self.__items.pop() 30 | 31 | def clear(self): 32 | self.__items.clear() 33 | -------------------------------------------------------------------------------- /base/utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/5A59/Zvm/d093558c567488472252a4f6f87cecbc0ec2bd38/base/utils/__init__.py -------------------------------------------------------------------------------- /base/utils/common_utils.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | 3 | import struct 4 | 5 | 6 | # 主要是给跳转指令用 7 | def get_short_from_bytes(byte1, byte2): 8 | val = (byte1 << 8) | byte2 9 | return struct.unpack('>h', val.to_bytes(2, byteorder='big'))[0] 10 | 11 | 12 | def get_int_from_bytes(data): 13 | if len(data) == 2: 14 | return struct.unpack('>h', data)[0] 15 | if len(data) == 4: 16 | return struct.unpack('>i', data)[0] 17 | return 0 18 | 19 | 20 | def get_float_from_bytes(data): 21 | return struct.unpack('>f', data)[0] 22 | 23 | 24 | def get_long_from_bytes(high, low): 25 | return struct.unpack('>q', high + low)[0] 26 | 27 | 28 | def get_double_from_bytes(high, low): 29 | return struct.unpack('>d', high + low)[0] 30 | 31 | 32 | def get_string_from_bytes(data): 33 | return data.decode('utf-8') 34 | -------------------------------------------------------------------------------- /base/utils/error_handler.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | 3 | 4 | def rise_runtime_error(msg): 5 | raise RuntimeError("jvm internal error: " + msg) 6 | 7 | 8 | def rise_null_point_error(): 9 | raise RuntimeError("error: java.lang.NullPointerException") 10 | 11 | 12 | def rise_class_cast_error(): 13 | raise RuntimeError("error: java.lang.ClassCastException") 14 | 15 | 16 | def rise_error(error): 17 | raise error 18 | 19 | 20 | class InternalError(Exception): 21 | pass 22 | 23 | 24 | class OutOfMemoryError(Exception): 25 | pass 26 | 27 | 28 | class StackOverflowError(Exception): 29 | pass 30 | 31 | 32 | class UnknownError(Exception): 33 | pass 34 | -------------------------------------------------------------------------------- /base/utils/print_utils.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | 3 | from base import jvm_config 4 | 5 | 6 | def print_error(msg): 7 | print("error: " + msg) 8 | 9 | 10 | def print_jvm_status(msg): 11 | if jvm_config.log_jvm_status: 12 | print(msg) 13 | 14 | 15 | def print_msg(msg): 16 | print(msg) 17 | 18 | 19 | class StreamPrinter(object): 20 | msgs = {} 21 | 22 | @staticmethod 23 | def print_all(thread): 24 | if thread in StreamPrinter.msgs: 25 | msgs = StreamPrinter.msgs[thread] 26 | for msg in msgs: 27 | print_msg(msg) 28 | 29 | @staticmethod 30 | def append_msg(thread, msg): 31 | if jvm_config.print_in_real_time: 32 | print_msg(msg) 33 | else: 34 | if thread in StreamPrinter.msgs: 35 | StreamPrinter.msgs[thread].append(msg) 36 | else: 37 | StreamPrinter.msgs[thread] = [] 38 | StreamPrinter.msgs[thread].append(msg) 39 | -------------------------------------------------------------------------------- /instruction/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/5A59/Zvm/d093558c567488472252a4f6f87cecbc0ec2bd38/instruction/__init__.py -------------------------------------------------------------------------------- /instruction/instruction.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | 3 | import abc 4 | import ctypes 5 | import struct 6 | 7 | from runtime.thread import Frame, LocalVars 8 | from runtime.jclass import ClassLoader, JString, JDouble, JLong, JClass, JFloat, JInteger 9 | from runtime.jobject import JObject, JArray, JRef 10 | from base.utils import print_utils, common_utils, error_handler 11 | from interpreter.code_parser import CodeParser 12 | from jthread.jthread import JThread 13 | 14 | ''' 15 | 以下指令没有测试 16 | wide 17 | dup2 18 | dup_x1 19 | dup_x2 20 | dup2_x1 21 | dup2_x2 22 | pop2 23 | if_xxx 24 | swap 25 | ''' 26 | 27 | ''' 28 | 未实现指令 29 | jsr 30 | ret 31 | invokeinterface 32 | monitorenter 33 | monitorexit 34 | multianewarray 35 | jsr_w 36 | breakpoint 37 | impdep1 38 | impdep2 39 | ''' 40 | 41 | 42 | class InsUtils(object): 43 | TYPE_INT = 1 44 | TYPE_FLOAT = 2 45 | TYPE_LONG = 3 46 | TYPE_DOUBLE = 4 47 | TYPE_REF = 5 48 | TYPE_ARRAY = 6 49 | TYPE_UNKNOWN = -1 50 | 51 | @staticmethod 52 | def get_type_by_descriptor(desc): 53 | if desc == 'I' or desc == 'B' or desc == 'C' or desc == 'S' or desc == 'Z': 54 | return InsUtils.TYPE_INT 55 | elif desc == 'F': 56 | return InsUtils.TYPE_FLOAT 57 | elif desc == 'J': 58 | return InsUtils.TYPE_LONG 59 | elif desc == 'D': 60 | return InsUtils.TYPE_DOUBLE 61 | elif desc[0] == 'L': 62 | return InsUtils.TYPE_REF 63 | elif desc[0] == '[': 64 | return InsUtils.TYPE_ARRAY 65 | else: 66 | return InsUtils.TYPE_UNKNOWN 67 | 68 | @staticmethod 69 | def check_ref_null(ref): 70 | if JRef.check_null(ref): 71 | error_handler.rise_null_point_error() 72 | 73 | 74 | class Instruction(object): 75 | code = None # 字节码 76 | name = None # 助记符 77 | 78 | def read_operands(self, code_parser): 79 | pass 80 | 81 | def execute_wrapper(self, frame): 82 | hex_code = '%x' % self.code 83 | print_utils.print_jvm_status('execute ins: ' + self.name + ' ' + hex_code + ' ' + str(frame) + '\n') 84 | self.execute(frame) 85 | 86 | @abc.abstractmethod 87 | def execute(self, frame): 88 | pass 89 | 90 | 91 | # 不是真正的指令集,但是有和指令差不多的功能 92 | class INNER_INS(Instruction): 93 | code = -1 94 | name = 'inner_ins' 95 | 96 | 97 | class INNER_INVOKE_C_INIT(INNER_INS): 98 | def __init__(self, jclass): 99 | super(INNER_INVOKE_C_INIT, self).__init__() 100 | self.jclass = jclass 101 | 102 | def execute(self, frame): 103 | method = None 104 | for m in self.jclass.methods: 105 | if m.name == '': 106 | method = m 107 | break 108 | if method is not None: 109 | n_frame = Frame(frame.thread, method) 110 | frame.thread.add_frame(n_frame) 111 | frame.pc = frame.thread.pc 112 | 113 | 114 | class ACONST_NULL(Instruction): 115 | code = 0x1 116 | name = 'aconst_null' 117 | 118 | def execute(self, frame): 119 | frame.operand_stack.push(None) 120 | 121 | 122 | class ALOAD(Instruction): 123 | code = 0x19 124 | name = 'aload' 125 | 126 | def __init__(self): 127 | super(ALOAD, self).__init__() 128 | self.index = -1 129 | 130 | def read_operands(self, code_parser): 131 | self.index = code_parser.read_op() 132 | 133 | def execute(self, frame): 134 | ref = frame.local_vars.get_ref(self.index) 135 | frame.operand_stack.push_ref(ref) 136 | 137 | 138 | class ALOAD_N(Instruction): 139 | @abc.abstractmethod 140 | def get_index(self): 141 | pass 142 | 143 | def execute(self, frame): 144 | ref = frame.local_vars.get_ref(self.get_index()) 145 | frame.operand_stack.push_ref(ref) 146 | 147 | 148 | class ALOAD_0(ALOAD_N): 149 | code = 0x2a 150 | name = 'aload_0' 151 | 152 | def get_index(self): 153 | return 0 154 | 155 | 156 | class ALOAD_1(ALOAD_N): 157 | code = 0x2b 158 | name = 'aload_1' 159 | 160 | def get_index(self): 161 | return 1 162 | 163 | 164 | class ALOAD_2(ALOAD_N): 165 | code = 0x2c 166 | name = 'aload_2' 167 | 168 | def get_index(self): 169 | return 2 170 | 171 | 172 | class ALOAD_3(ALOAD_N): 173 | code = 0x2d 174 | name = 'aload_3' 175 | 176 | def get_index(self): 177 | return 3 178 | 179 | 180 | class ARETURN(Instruction): 181 | code = 0xb0 182 | name = 'areturn' 183 | 184 | def execute(self, frame): 185 | frame.thread.pop_frame() 186 | r_value = frame.operand_stack.pop_ref() 187 | c_frame = frame.thread.top_frame() 188 | c_frame.operand_stack.push_ref(r_value) 189 | 190 | 191 | class ASTORE(Instruction): 192 | code = 0x3a 193 | name = 'astore' 194 | 195 | def __init__(self): 196 | super(ASTORE, self).__init__() 197 | self.index = -1 198 | 199 | def read_operands(self, code_parser): 200 | self.index = code_parser.read_op() 201 | 202 | def execute(self, frame): 203 | ref = frame.operand_stack.pop_ref() 204 | frame.local_vars.add_ref(self.index, ref) 205 | 206 | 207 | class ASTORE_N(Instruction): 208 | @abc.abstractmethod 209 | def get_index(self): 210 | pass 211 | 212 | def execute(self, frame): 213 | ref = frame.operand_stack.pop_ref() 214 | frame.local_vars.add_ref(self.get_index(), ref) 215 | 216 | 217 | class ASTORE_0(ASTORE_N): 218 | code = 0x4b 219 | name = 'astore_0' 220 | 221 | def get_index(self): 222 | return 0 223 | 224 | 225 | class ASTORE_1(ASTORE_N): 226 | code = 0x4c 227 | name = 'astore_1' 228 | 229 | def get_index(self): 230 | return 1 231 | 232 | 233 | class ASTORE_2(ASTORE_N): 234 | code = 0x4d 235 | name = 'astore_2' 236 | 237 | def get_index(self): 238 | return 2 239 | 240 | 241 | class ASTORE_3(ASTORE_N): 242 | code = 0x4e 243 | name = 'astore_3' 244 | 245 | def get_index(self): 246 | return 3 247 | 248 | 249 | class BIPUSH(Instruction): 250 | code = 0x10 251 | name = 'bipush' 252 | 253 | def __init__(self): 254 | super(BIPUSH, self).__init__() 255 | self.byte = 0 256 | 257 | def read_operands(self, code_parser): 258 | self.byte = code_parser.read_op() 259 | 260 | def execute(self, frame): 261 | frame.operand_stack.push_int(ctypes.c_byte(self.byte).value) 262 | 263 | 264 | class DUP(Instruction): 265 | code = 0x59 266 | name = 'dup' 267 | 268 | def execute(self, frame): 269 | operand_stack = frame.operand_stack 270 | value = operand_stack.top() 271 | if isinstance(value, JRef): 272 | value = value.clone() 273 | operand_stack.push(value) 274 | 275 | 276 | class DUP_X1(Instruction): 277 | code = 0x5a 278 | name = 'dup_x1' 279 | 280 | def execute(self, frame): 281 | operand_stack = frame.operand_stack 282 | value1 = operand_stack.top() 283 | value2 = operand_stack.top(2) 284 | if isinstance(value1, JRef): 285 | value1 = value1.clone() 286 | if isinstance(value2, JRef): 287 | value1 = value2.clone() 288 | operand_stack.push(value2) 289 | operand_stack.push(value1) 290 | 291 | 292 | class DUP_X2(Instruction): 293 | code = 0x5b 294 | name = 'dup_x2' 295 | 296 | def execute(self, frame): 297 | operand_stack = frame.operand_stack 298 | value1 = operand_stack.top() 299 | value2 = operand_stack.top(2) 300 | if operand_stack.is_top_type1(2): 301 | if isinstance(value1, JRef): 302 | value1 = value1.clone() 303 | operand_stack.push(value2) 304 | operand_stack.push(value1) 305 | else: 306 | value3 = operand_stack.top(3) 307 | if isinstance(value1, JRef): 308 | value1 = value1.clone() 309 | if isinstance(value2, JRef): 310 | value1 = value2.clone() 311 | if isinstance(value3, JRef): 312 | value1 = value3.clone() 313 | operand_stack.push(value3) 314 | operand_stack.push(value2) 315 | operand_stack.push(value1) 316 | 317 | 318 | class DUP2(Instruction): 319 | code = 0x5c 320 | name = 'dup2' 321 | 322 | def execute(self, frame): 323 | operand_stack = frame.operand_stack 324 | value = operand_stack.top() 325 | if operand_stack.is_top_type1(): 326 | operand_stack.push(value) 327 | return 328 | 329 | value2 = operand_stack.top(2) 330 | if isinstance(value, JRef): 331 | value = value.clone() 332 | if isinstance(value2, JRef): 333 | value = value.clone() 334 | operand_stack.push(value2) 335 | operand_stack.push(value) 336 | 337 | 338 | class DUP2_X1(Instruction): 339 | code = 0x5d 340 | name = 'dup2_x1' 341 | 342 | def execute(self, frame): 343 | operand_stack = frame.operand_stack 344 | value1 = operand_stack.top() 345 | value2 = operand_stack.top(2) 346 | if operand_stack.is_top_type1(): 347 | if isinstance(value2, JRef): 348 | value1 = value2.clone() 349 | operand_stack.push(value2) 350 | operand_stack.push(value1) 351 | else: 352 | value3 = operand_stack.top(3) 353 | if isinstance(value1, JRef): 354 | value1 = value1.clone() 355 | if isinstance(value2, JRef): 356 | value1 = value2.clone() 357 | if isinstance(value3, JRef): 358 | value1 = value3.clone() 359 | operand_stack.push(value3) 360 | operand_stack.push(value2) 361 | operand_stack.push(value1) 362 | 363 | 364 | class DUP2_X2(Instruction): 365 | code = 0x5e 366 | name = 'dup2_x2' 367 | 368 | def execute(self, frame): 369 | operand_stack = frame.operand_stack 370 | value1 = operand_stack.top() 371 | value2 = operand_stack.top(2) 372 | value3 = operand_stack.top(3) 373 | if operand_stack.is_top_type1() or operand_stack.is_top_type1(2) or operand_stack.is_top_type1(3): 374 | if isinstance(value1, JRef): 375 | value1 = value1.clone() 376 | if isinstance(value2, JRef): 377 | value1 = value2.clone() 378 | if isinstance(value3, JRef): 379 | value1 = value3.clone() 380 | operand_stack.push(value3) 381 | operand_stack.push(value2) 382 | operand_stack.push(value1) 383 | else: 384 | value4 = operand_stack.top(4) 385 | if isinstance(value1, JRef): 386 | value1 = value1.clone() 387 | if isinstance(value2, JRef): 388 | value1 = value2.clone() 389 | if isinstance(value3, JRef): 390 | value1 = value3.clone() 391 | if isinstance(value4, JRef): 392 | value1 = value4.clone() 393 | operand_stack.push(value4) 394 | operand_stack.push(value3) 395 | operand_stack.push(value2) 396 | operand_stack.push(value1) 397 | 398 | 399 | class PUTSTATIC(Instruction): 400 | code = 0xb3 401 | name = 'putstatic' 402 | 403 | def __init__(self): 404 | super(PUTSTATIC, self).__init__() 405 | self.index = -1 406 | 407 | def read_operands(self, code_parser): 408 | index1 = code_parser.read_op() 409 | index2 = code_parser.read_op() 410 | self.index = (index1 << 8) | index2 411 | 412 | def execute(self, frame): 413 | constant_pool = frame.method.jclass.constant_pool 414 | ref = constant_pool.constants[self.index] 415 | ref.resolve_field(frame.method.jclass.class_loader) 416 | ftype = InsUtils.get_type_by_descriptor(ref.descriptor) 417 | jclass = ref.cache_class 418 | if not jclass.has_inited: 419 | c_init = INNER_INVOKE_C_INIT(jclass) 420 | c_init.execute(frame) 421 | jclass.has_inited = True 422 | return 423 | slots = jclass.static_fields 424 | slot = slots[ref.field.name] 425 | operand_stack = frame.operand_stack 426 | if ftype == InsUtils.TYPE_INT: 427 | slot.num = operand_stack.pop_int() 428 | elif ftype == InsUtils.TYPE_FLOAT: 429 | slot.num = operand_stack.pop_float() 430 | elif ftype == InsUtils.TYPE_LONG: 431 | slot.num = operand_stack.pop_long() 432 | elif ftype == InsUtils.TYPE_DOUBLE: 433 | slot.num = operand_stack.pop_double() 434 | else: 435 | slot.ref = operand_stack.pop_ref() 436 | 437 | 438 | class GETSTATIC(Instruction): 439 | code = 0xb2 440 | name = 'getstatic' 441 | 442 | def __init__(self): 443 | super(GETSTATIC, self).__init__() 444 | self.index = -1 445 | 446 | def read_operands(self, code_parser): 447 | index1 = code_parser.read_op() 448 | index2 = code_parser.read_op() 449 | self.index = (index1 << 8) | index2 450 | 451 | def execute(self, frame): 452 | constant_pool = frame.method.jclass.constant_pool 453 | ref = constant_pool.constants[self.index] 454 | ref.resolve_field(frame.method.jclass.class_loader) 455 | ftype = InsUtils.get_type_by_descriptor(ref.descriptor) 456 | jclass = ref.cache_class 457 | if not jclass.has_inited: 458 | c_init = INNER_INVOKE_C_INIT(jclass) 459 | c_init.execute(frame) 460 | jclass.has_inited = True 461 | return 462 | slots = jclass.static_fields 463 | val = slots[ref.field.name] 464 | if val is not None: 465 | if val.num is not None: 466 | if ftype == InsUtils.TYPE_INT: 467 | frame.operand_stack.push_int(val.num) 468 | elif ftype == InsUtils.TYPE_FLOAT: 469 | frame.operand_stack.push_float(val.num) 470 | elif ftype == InsUtils.TYPE_LONG: 471 | frame.operand_stack.push_long(val.num) 472 | elif ftype == InsUtils.TYPE_DOUBLE: 473 | frame.operand_stack.push_double(val.num) 474 | elif val.ref is not None: 475 | frame.operand_stack.push_ref(val.ref) 476 | else: 477 | frame.operand_stack.push(None) 478 | else: 479 | frame.operand_stack.push(None) 480 | 481 | 482 | class JUMP_INC(Instruction): 483 | def jump_by(self, frame, offset): 484 | frame.pc = frame.thread.pc + offset 485 | 486 | def jump_to(self, frame, pc): 487 | frame.pc = pc 488 | 489 | 490 | class GOTO(JUMP_INC): 491 | code = 0xa7 492 | name = 'goto' 493 | 494 | def __init__(self): 495 | super(GOTO, self).__init__() 496 | self.branch = 0 497 | 498 | def read_operands(self, code_parser): 499 | branch1 = code_parser.read_op() 500 | branch2 = code_parser.read_op() 501 | self.branch = common_utils.get_short_from_bytes(branch1, branch2) 502 | 503 | def execute(self, frame): 504 | self.jump_by(frame, self.branch) 505 | 506 | 507 | class GOTO_W(JUMP_INC): 508 | code = 0xc8 509 | name = 'goto_w' 510 | 511 | def __init__(self): 512 | super(GOTO_W, self).__init__() 513 | self.branch = 0 514 | 515 | def read_operands(self, code_parser): 516 | branch1 = code_parser.read_op() 517 | branch2 = code_parser.read_op() 518 | branch3 = code_parser.read_op() 519 | branch4 = code_parser.read_op() 520 | self.branch = (branch1 << 24) | (branch2 << 16) | (branch3 << 8) | branch4 521 | 522 | def execute(self, frame): 523 | self.jump_by(frame, self.branch) 524 | 525 | 526 | class IASTORE(Instruction): 527 | code = 0x4f 528 | name = 'iastore' 529 | 530 | def execute(self, frame): 531 | operand_stack = frame.operand_stack 532 | value = operand_stack.pop_int() 533 | index = operand_stack.pop_int() 534 | aref = operand_stack.pop_ref() 535 | InsUtils.check_ref_null(aref) 536 | aref.handler.obj.add_item(index, value) 537 | 538 | 539 | class IALOAD(Instruction): 540 | code = 0x2e 541 | name = 'iaload' 542 | 543 | def execute(self, frame): 544 | operand_stack = frame.operand_stack 545 | index = operand_stack.pop_int() 546 | aref = operand_stack.pop_ref() 547 | InsUtils.check_ref_null(aref) 548 | val = aref.handler.obj.get_item(index) 549 | operand_stack.push_int(val) 550 | 551 | 552 | class CASTORE(Instruction): 553 | code = 0x55 554 | name = 'castore' 555 | 556 | def execute(self, frame): 557 | operand_stack = frame.operand_stack 558 | value = operand_stack.pop_int() 559 | index = operand_stack.pop_int() 560 | aref = operand_stack.pop_ref() 561 | InsUtils.check_ref_null(aref) 562 | aref.handler.obj.add_item(index, value) 563 | 564 | 565 | class CALOAD(Instruction): 566 | code = 0x34 567 | name = 'caload' 568 | 569 | def execute(self, frame): 570 | operand_stack = frame.operand_stack 571 | index = operand_stack.pop_int() 572 | aref = operand_stack.pop_ref() 573 | InsUtils.check_ref_null(aref) 574 | val = aref.handler.obj.get_item(index) 575 | operand_stack.push_int(val) 576 | 577 | 578 | class DASTORE(Instruction): 579 | code = 0x52 580 | name = 'dastore' 581 | 582 | def execute(self, frame): 583 | operand_stack = frame.operand_stack 584 | value = operand_stack.pop_double() 585 | index = operand_stack.pop_int() 586 | aref = operand_stack.pop_ref() 587 | InsUtils.check_ref_null(aref) 588 | aref.handler.obj.add_item(index, value) 589 | 590 | 591 | class DALOAD(Instruction): 592 | code = 0x31 593 | name = 'daload' 594 | 595 | def execute(self, frame): 596 | operand_stack = frame.operand_stack 597 | index = operand_stack.pop_int() 598 | aref = operand_stack.pop_ref() 599 | InsUtils.check_ref_null(aref) 600 | val = aref.handler.obj.get_item(index) 601 | operand_stack.push_double(val) 602 | 603 | 604 | class FASTORE(Instruction): 605 | code = 0x51 606 | name = 'fastore' 607 | 608 | def execute(self, frame): 609 | operand_stack = frame.operand_stack 610 | value = operand_stack.pop_float() 611 | index = operand_stack.pop_int() 612 | aref = operand_stack.pop_ref() 613 | InsUtils.check_ref_null(aref) 614 | aref.handler.obj.add_item(index, value) 615 | 616 | 617 | class FALOAD(Instruction): 618 | code = 0x30 619 | name = 'faload' 620 | 621 | def execute(self, frame): 622 | operand_stack = frame.operand_stack 623 | index = operand_stack.pop_int() 624 | aref = operand_stack.pop_ref() 625 | InsUtils.check_ref_null(aref) 626 | val = aref.handler.obj.get_item(index) 627 | operand_stack.push_float(val) 628 | 629 | 630 | class LASTORE(Instruction): 631 | code = 0x50 632 | name = 'lastore' 633 | 634 | def execute(self, frame): 635 | operand_stack = frame.operand_stack 636 | value = operand_stack.pop_long() 637 | index = operand_stack.pop_int() 638 | aref = operand_stack.pop_ref() 639 | InsUtils.check_ref_null(aref) 640 | aref.handler.obj.add_item(index, value) 641 | 642 | 643 | class LALOAD(Instruction): 644 | code = 0x2f 645 | name = 'laload' 646 | 647 | def execute(self, frame): 648 | operand_stack = frame.operand_stack 649 | index = operand_stack.pop_int() 650 | aref = operand_stack.pop_ref() 651 | InsUtils.check_ref_null(aref) 652 | val = aref.handler.obj.get_item(index) 653 | operand_stack.push_long(val) 654 | 655 | 656 | class SASTORE(Instruction): 657 | code = 0x56 658 | name = 'sastore' 659 | 660 | def execute(self, frame): 661 | operand_stack = frame.operand_stack 662 | value = operand_stack.pop_int() 663 | index = operand_stack.pop_int() 664 | aref = operand_stack.pop_ref() 665 | InsUtils.check_ref_null(aref) 666 | aref.handler.obj.add_item(index, value) 667 | 668 | 669 | class SALOAD(Instruction): 670 | code = 0x35 671 | name = 'saload' 672 | 673 | def execute(self, frame): 674 | operand_stack = frame.operand_stack 675 | index = operand_stack.pop_int() 676 | aref = operand_stack.pop_ref() 677 | InsUtils.check_ref_null(aref) 678 | val = aref.handler.obj.get_item(index) 679 | operand_stack.push_int(val) 680 | 681 | 682 | class AASTORE(Instruction): 683 | code = 0x53 684 | name = 'aastore' 685 | 686 | def execute(self, frame): 687 | operand_stack = frame.operand_stack 688 | value = operand_stack.pop_ref() 689 | index = operand_stack.pop_int() 690 | aref = operand_stack.pop_ref() 691 | InsUtils.check_ref_null(aref) 692 | aref.handler.obj.add_ref_item(index, value) 693 | 694 | 695 | class AALOAD(Instruction): 696 | code = 0x32 697 | name = 'aaload' 698 | 699 | def execute(self, frame): 700 | operand_stack = frame.operand_stack 701 | index = operand_stack.pop_int() 702 | aref = operand_stack.pop_ref() 703 | InsUtils.check_ref_null(aref) 704 | val = aref.handler.obj.get_item(index) 705 | operand_stack.push_ref(val) 706 | 707 | 708 | class BASTORE(Instruction): 709 | code = 0x54 710 | name = 'bastore' 711 | 712 | def execute(self, frame): 713 | operand_stack = frame.operand_stack 714 | value = operand_stack.pop_int() 715 | index = operand_stack.pop_int() 716 | aref = operand_stack.pop_ref() 717 | InsUtils.check_ref_null(aref) 718 | aref.handler.obj.add_item(index, value) 719 | 720 | 721 | class BALOAD(Instruction): 722 | code = 0x33 723 | name = 'baload' 724 | 725 | def execute(self, frame): 726 | operand_stack = frame.operand_stack 727 | index = operand_stack.pop_int() 728 | aref = operand_stack.pop_ref() 729 | InsUtils.check_ref_null(aref) 730 | val = aref.handler.obj.get_item(index) 731 | operand_stack.push_int(val) 732 | 733 | 734 | class IINC(Instruction): 735 | code = 0x84 736 | name = 'iinc' 737 | 738 | def __init__(self): 739 | super(IINC, self).__init__() 740 | self.index = 0 741 | self.const = 0 742 | 743 | def read_operands(self, code_parser): 744 | self.index = code_parser.read_op() 745 | self.const = code_parser.read_op() 746 | 747 | def execute(self, frame): 748 | val = frame.local_vars.get_int(self.index) 749 | val += self.const 750 | frame.local_vars.add_int(self.index, val) 751 | 752 | 753 | class I2L(Instruction): 754 | code = 0x85 755 | name = 'i2l' 756 | 757 | def execute(self, frame): 758 | val = frame.operand_stack.pop_int() 759 | frame.operand_stack.push_long(val) 760 | 761 | 762 | class I2F(Instruction): 763 | code = 0x86 764 | name = 'i2f' 765 | 766 | def execute(self, frame): 767 | val = frame.operand_stack.pop_int() 768 | frame.operand_stack.push_float(ctypes.c_float(val).value) 769 | 770 | 771 | class I2D(Instruction): 772 | code = 0x87 773 | name = 'i2d' 774 | 775 | def execute(self, frame): 776 | val = frame.operand_stack.pop_int() 777 | frame.operand_stack.push_double(ctypes.c_double(val).value) 778 | 779 | 780 | class L2I(Instruction): 781 | code = 0x88 782 | name = 'l2i' 783 | 784 | def execute(self, frame): 785 | val = frame.operand_stack.pop_long() 786 | frame.operand_stack.push_int(ctypes.c_int32(val).value) 787 | 788 | 789 | class L2F(Instruction): 790 | code = 0x89 791 | name = 'l2f' 792 | 793 | def execute(self, frame): 794 | val = frame.operand_stack.pop_long() 795 | frame.operand_stack.push_float(ctypes.c_float(val).value) 796 | 797 | 798 | class L2D(Instruction): 799 | code = 0x8a 800 | name = 'l2d' 801 | 802 | def execute(self, frame): 803 | val = frame.operand_stack.pop_long() 804 | frame.operand_stack.push_double(ctypes.c_double(val).value) 805 | 806 | 807 | class F2I(Instruction): 808 | code = 0x8b 809 | name = 'f2i' 810 | 811 | def execute(self, frame): 812 | val = frame.operand_stack.pop_float() 813 | frame.operand_stack.push_int(ctypes.c_int32(val).value) 814 | 815 | 816 | class F2L(Instruction): 817 | code = 0x8c 818 | name = 'f2l' 819 | 820 | def execute(self, frame): 821 | val = frame.operand_stack.pop_float() 822 | frame.operand_stack.push_long(ctypes.c_long(val).value) 823 | 824 | 825 | class F2D(Instruction): 826 | code = 0x8d 827 | name = 'f2d' 828 | 829 | def execute(self, frame): 830 | val = frame.operand_stack.pop_float() 831 | frame.operand_stack.push_double(ctypes.c_double(val).value) 832 | 833 | 834 | class D2I(Instruction): 835 | code = 0x8e 836 | name = 'd2i' 837 | 838 | def execute(self, frame): 839 | val = frame.operand_stack.pop_double() 840 | frame.operand_stack.push_int(ctypes.c_int32(val).value) 841 | 842 | 843 | class D2L(Instruction): 844 | code = 0x8f 845 | name = 'd2l' 846 | 847 | def execute(self, frame): 848 | val = frame.operand_stack.pop_double() 849 | frame.operand_stack.push_long(ctypes.c_long(val).value) 850 | 851 | 852 | class D2F(Instruction): 853 | code = 0x90 854 | name = 'd2f' 855 | 856 | def execute(self, frame): 857 | val = frame.operand_stack.pop_double() 858 | frame.operand_stack.push_float(ctypes.c_float(val).value) 859 | 860 | 861 | class I2B(Instruction): 862 | code = 0x91 863 | name = 'i2b' 864 | 865 | def execute(self, frame): 866 | val = frame.operand_stack.pop_int() 867 | frame.operand_stack.push_int(ctypes.c_byte(val).value) 868 | 869 | 870 | class I2C(Instruction): 871 | code = 0x92 872 | name = 'i2c' 873 | 874 | def execute(self, frame): 875 | val = frame.operand_stack.pop_int() 876 | frame.operand_stack.push_int(ctypes.c_char(val).value) 877 | 878 | 879 | class I2S(Instruction): 880 | code = 0x93 881 | name = 'i2s' 882 | 883 | def execute(self, frame): 884 | val = frame.operand_stack.pop_int() 885 | frame.operand_stack.push_int(ctypes.c_short(val).value) 886 | 887 | 888 | class LCMP(Instruction): 889 | code = 0x94 890 | name = 'lcmp' 891 | 892 | def execute(self, frame): 893 | value2 = frame.operand_stack.pop_long() 894 | value1 = frame.operand_stack.pop_long() 895 | if value1 > value2: 896 | frame.operand_stack.push_int(1) 897 | elif value1 < value2: 898 | frame.operand_stack.push_int(-1) 899 | else: 900 | frame.operand_stack.push_int(0) 901 | 902 | 903 | class FCMPOP(Instruction): 904 | # TODO: 对 fcmpl 和 fcmpd 没有做区分 905 | def execute(self, frame): 906 | value2 = frame.operand_stack.pop_float() 907 | value1 = frame.operand_stack.pop_float() 908 | if value1 > value2: 909 | frame.operand_stack.push_int(1) 910 | elif value1 < value2: 911 | frame.operand_stack.push_int(-1) 912 | else: 913 | frame.operand_stack.push_int(0) 914 | 915 | 916 | class FCMPL(FCMPOP): 917 | code = 0x95 918 | name = 'fcmpl' 919 | 920 | 921 | class FCMPD(FCMPOP): 922 | code = 0x96 923 | name = 'fcmpd' 924 | 925 | 926 | class DCMPOP(Instruction): 927 | # TODO: 对 dcmpl 和 dcmpd 没有做区分 928 | def execute(self, frame): 929 | value2 = frame.operand_stack.pop_double() 930 | value1 = frame.operand_stack.pop_double() 931 | if value1 > value2: 932 | frame.operand_stack.push_int(1) 933 | elif value1 < value2: 934 | frame.operand_stack.push_int(-1) 935 | else: 936 | frame.operand_stack.push_int(0) 937 | 938 | 939 | class DCMPL(DCMPOP): 940 | code = 0x97 941 | name = 'dcmpl' 942 | 943 | 944 | class DCMPD(FCMPOP): 945 | code = 0x98 946 | name = 'dcmpd' 947 | 948 | 949 | class ICONST_I(Instruction): 950 | @abc.abstractmethod 951 | def get_index(self): 952 | pass 953 | 954 | def execute(self, frame): 955 | index = self.get_index() 956 | stack = frame.operand_stack 957 | stack.push_int(index) 958 | 959 | 960 | class ICONST_M1(ICONST_I): 961 | code = 0x2 962 | name = 'iconst_m1' 963 | 964 | def get_index(self): 965 | return -1 966 | 967 | 968 | class ICONST_0(ICONST_I): 969 | code = 0x3 970 | name = 'iconst_0' 971 | 972 | def get_index(self): 973 | return 0 974 | 975 | 976 | class ICONST_1(ICONST_I): 977 | code = 0x4 978 | name = 'iconst_1' 979 | 980 | def get_index(self): 981 | return 1 982 | 983 | 984 | class ICONST_2(ICONST_I): 985 | code = 0x5 986 | name = 'iconst_2' 987 | 988 | def get_index(self): 989 | return 2 990 | 991 | 992 | class ICONST_3(ICONST_I): 993 | code = 0x6 994 | name = 'iconst_3' 995 | 996 | def get_index(self): 997 | return 3 998 | 999 | 1000 | class ICONST_4(ICONST_I): 1001 | code = 0x7 1002 | name = 'iconst_4' 1003 | 1004 | def get_index(self): 1005 | return 4 1006 | 1007 | 1008 | class ICONST_5(ICONST_I): 1009 | code = 0x8 1010 | name = 'iconst_5' 1011 | 1012 | def get_index(self): 1013 | return 5 1014 | 1015 | 1016 | class LCONST_L(Instruction): 1017 | @abc.abstractmethod 1018 | def get_index(self): 1019 | pass 1020 | 1021 | def execute(self, frame): 1022 | index = self.get_index() 1023 | stack = frame.operand_stack 1024 | stack.push_long(index) 1025 | 1026 | 1027 | class LCONST_0(LCONST_L): 1028 | code = 0x9 1029 | name = 'lconst_0' 1030 | 1031 | def get_index(self): 1032 | return 0 1033 | 1034 | 1035 | class LCONST_1(LCONST_L): 1036 | code = 0xa 1037 | name = 'lconst_1' 1038 | 1039 | def get_index(self): 1040 | return 1 1041 | 1042 | 1043 | class FCONST_L(Instruction): 1044 | @abc.abstractmethod 1045 | def get_index(self): 1046 | pass 1047 | 1048 | def execute(self, frame): 1049 | index = self.get_index() 1050 | stack = frame.operand_stack 1051 | stack.push_float(index) 1052 | 1053 | 1054 | class FCONST_0(FCONST_L): 1055 | code = 0xb 1056 | name = 'fconst_0' 1057 | 1058 | def get_index(self): 1059 | return 0.0 1060 | 1061 | 1062 | class FCONST_1(FCONST_L): 1063 | code = 0xc 1064 | name = 'fconst_1' 1065 | 1066 | def get_index(self): 1067 | return 1.0 1068 | 1069 | 1070 | class FCONST_2(FCONST_L): 1071 | code = 0xd 1072 | name = 'fconst_2' 1073 | 1074 | def get_index(self): 1075 | return 2.0 1076 | 1077 | 1078 | class DCONST_L(Instruction): 1079 | @abc.abstractmethod 1080 | def get_index(self): 1081 | pass 1082 | 1083 | def execute(self, frame): 1084 | index = self.get_index() 1085 | stack = frame.operand_stack 1086 | stack.push_double(index) 1087 | 1088 | 1089 | class DCONST_0(FCONST_L): 1090 | code = 0xe 1091 | name = 'dconst_0' 1092 | 1093 | def get_index(self): 1094 | return 0.0 1095 | 1096 | 1097 | class DCONST_1(FCONST_L): 1098 | code = 0xf 1099 | name = 'dconst_1' 1100 | 1101 | def get_index(self): 1102 | return 1.0 1103 | 1104 | 1105 | class ILOAD(Instruction): 1106 | code = 0x15 1107 | name = 'iload' 1108 | 1109 | def __init__(self): 1110 | super(ILOAD, self).__init__() 1111 | self.index = 0 1112 | 1113 | def read_operands(self, code_parser): 1114 | self.index = code_parser.read_op() 1115 | 1116 | def execute(self, frame): 1117 | local_vars = frame.local_vars 1118 | operand_stack = frame.operand_stack 1119 | value = local_vars.get_int(self.index) 1120 | operand_stack.push_int(value) 1121 | 1122 | 1123 | class ILOAD_N(Instruction): 1124 | @abc.abstractmethod 1125 | def get_index(self): 1126 | pass 1127 | 1128 | def execute(self, frame): 1129 | index = self.get_index() 1130 | local_vars = frame.local_vars 1131 | operand_stack = frame.operand_stack 1132 | value = local_vars.get_int(index) 1133 | operand_stack.push_int(value) 1134 | 1135 | 1136 | class ILOAD_0(ILOAD_N): 1137 | code = 0x1a 1138 | name = 'iload_0' 1139 | 1140 | def get_index(self): 1141 | return 0 1142 | 1143 | 1144 | class ILOAD_1(ILOAD_N): 1145 | code = 0x1b 1146 | name = 'iload_1' 1147 | 1148 | def get_index(self): 1149 | return 1 1150 | 1151 | 1152 | class ILOAD_2(ILOAD_N): 1153 | code = 0x1c 1154 | name = 'iload_2' 1155 | 1156 | def get_index(self): 1157 | return 2 1158 | 1159 | 1160 | class ILOAD_3(ILOAD_N): 1161 | code = 0x1d 1162 | name = 'iload_3' 1163 | 1164 | def get_index(self): 1165 | return 3 1166 | 1167 | 1168 | class DLOAD_N(Instruction): 1169 | @abc.abstractmethod 1170 | def get_index(self): 1171 | pass 1172 | 1173 | def execute(self, frame): 1174 | index = self.get_index() 1175 | local_vars = frame.local_vars 1176 | operand_stack = frame.operand_stack 1177 | value = local_vars.get_double(index) 1178 | operand_stack.push_double(value) 1179 | 1180 | 1181 | class DLOAD(DLOAD_N): 1182 | code = 0x18 1183 | name = 'dload' 1184 | 1185 | def __init__(self): 1186 | super(DLOAD, self).__init__() 1187 | self.index = 0 1188 | 1189 | def read_operands(self, code_parser): 1190 | self.index = code_parser.read_op() 1191 | 1192 | def get_index(self): 1193 | return self.index 1194 | 1195 | 1196 | class DLOAD_0(DLOAD_N): 1197 | code = 0x26 1198 | name = 'dload_0' 1199 | 1200 | def get_index(self): 1201 | return 0 1202 | 1203 | 1204 | class DLOAD_1(DLOAD_N): 1205 | code = 0x27 1206 | name = 'dload_1' 1207 | 1208 | def get_index(self): 1209 | return 1 1210 | 1211 | 1212 | class DLOAD_2(DLOAD_N): 1213 | code = 0x28 1214 | name = 'dload_2' 1215 | 1216 | def get_index(self): 1217 | return 2 1218 | 1219 | 1220 | class DLOAD_3(DLOAD_N): 1221 | code = 0x29 1222 | name = 'dload_3' 1223 | 1224 | def get_index(self): 1225 | return 3 1226 | 1227 | 1228 | class FLOAD_N(Instruction): 1229 | @abc.abstractmethod 1230 | def get_index(self): 1231 | pass 1232 | 1233 | def execute(self, frame): 1234 | index = self.get_index() 1235 | local_vars = frame.local_vars 1236 | operand_stack = frame.operand_stack 1237 | value = local_vars.get_float(index) 1238 | operand_stack.push_float(value) 1239 | 1240 | 1241 | class FLOAD(FLOAD_N): 1242 | code = 0x17 1243 | name = 'fload' 1244 | 1245 | def __init__(self): 1246 | super(FLOAD, self).__init__() 1247 | self.index = 0 1248 | 1249 | def read_operands(self, code_parser): 1250 | self.index = code_parser.read_op() 1251 | 1252 | def get_index(self): 1253 | return self.index 1254 | 1255 | 1256 | class FLOAD_0(FLOAD_N): 1257 | code = 0x22 1258 | name = 'fload_0' 1259 | 1260 | def get_index(self): 1261 | return 0 1262 | 1263 | 1264 | class FLOAD_1(FLOAD_N): 1265 | code = 0x23 1266 | name = 'fload_1' 1267 | 1268 | def get_index(self): 1269 | return 1 1270 | 1271 | 1272 | class FLOAD_2(FLOAD_N): 1273 | code = 0x24 1274 | name = 'fload_2' 1275 | 1276 | def get_index(self): 1277 | return 2 1278 | 1279 | 1280 | class FLOAD_3(FLOAD_N): 1281 | code = 0x25 1282 | name = 'fload_3' 1283 | 1284 | def get_index(self): 1285 | return 3 1286 | 1287 | 1288 | class LLOAD_N(Instruction): 1289 | @abc.abstractmethod 1290 | def get_index(self): 1291 | pass 1292 | 1293 | def execute(self, frame): 1294 | index = self.get_index() 1295 | local_vars = frame.local_vars 1296 | operand_stack = frame.operand_stack 1297 | value = local_vars.get_long(index) 1298 | operand_stack.push_long(value) 1299 | 1300 | 1301 | class LLOAD(LLOAD_N): 1302 | code = 0x16 1303 | name = 'lload' 1304 | 1305 | def __init__(self): 1306 | super(LLOAD, self).__init__() 1307 | self.index = 0 1308 | 1309 | def read_operands(self, code_parser): 1310 | self.index = code_parser.read_op() 1311 | 1312 | def get_index(self): 1313 | return self.index 1314 | 1315 | 1316 | class LLOAD_0(LLOAD_N): 1317 | code = 0x1e 1318 | name = 'lload_0' 1319 | 1320 | def get_index(self): 1321 | return 0 1322 | 1323 | 1324 | class LLOAD_1(LLOAD_N): 1325 | code = 0x1f 1326 | name = 'lload_1' 1327 | 1328 | def get_index(self): 1329 | return 1 1330 | 1331 | 1332 | class LLOAD_2(LLOAD_N): 1333 | code = 0x20 1334 | name = 'lload_2' 1335 | 1336 | def get_index(self): 1337 | return 2 1338 | 1339 | 1340 | class LLOAD_3(LLOAD_N): 1341 | code = 0x21 1342 | name = 'lload_3' 1343 | 1344 | def get_index(self): 1345 | return 3 1346 | 1347 | 1348 | class IADD(Instruction): 1349 | code = 0x60 1350 | name = 'iadd' 1351 | 1352 | def execute(self, frame): 1353 | operand_stack = frame.operand_stack 1354 | val1 = operand_stack.pop_int() 1355 | val2 = operand_stack.pop_int() 1356 | res = val1 + val2 1357 | operand_stack.push_int(res) 1358 | 1359 | 1360 | class LADD(Instruction): 1361 | code = 0x61 1362 | name = 'ladd' 1363 | 1364 | def execute(self, frame): 1365 | operand_stack = frame.operand_stack 1366 | val1 = operand_stack.pop_long() 1367 | val2 = operand_stack.pop_long() 1368 | res = val1 + val2 1369 | operand_stack.push_long(res) 1370 | 1371 | 1372 | class FADD(Instruction): 1373 | code = 0x62 1374 | name = 'fadd' 1375 | 1376 | def execute(self, frame): 1377 | operand_stack = frame.operand_stack 1378 | val1 = operand_stack.pop_float() 1379 | val2 = operand_stack.pop_float() 1380 | res = val1 + val2 1381 | operand_stack.push_float(res) 1382 | 1383 | 1384 | class DADD(Instruction): 1385 | code = 0x63 1386 | name = 'dadd' 1387 | 1388 | def execute(self, frame): 1389 | operand_stack = frame.operand_stack 1390 | val1 = operand_stack.pop_double() 1391 | val2 = operand_stack.pop_double() 1392 | res = val1 + val2 1393 | operand_stack.push_double(res) 1394 | 1395 | 1396 | class ISUB(Instruction): 1397 | code = 0x64 1398 | name = 'isub' 1399 | 1400 | def execute(self, frame): 1401 | operand_stack = frame.operand_stack 1402 | val1 = operand_stack.pop_int() 1403 | val2 = operand_stack.pop_int() 1404 | res = val1 - val2 1405 | operand_stack.push_int(res) 1406 | 1407 | 1408 | class LSUB(Instruction): 1409 | code = 0x65 1410 | name = 'lsub' 1411 | 1412 | def execute(self, frame): 1413 | operand_stack = frame.operand_stack 1414 | val1 = operand_stack.pop_long() 1415 | val2 = operand_stack.pop_long() 1416 | res = val1 - val2 1417 | operand_stack.push_long(res) 1418 | 1419 | 1420 | class FSUB(Instruction): 1421 | code = 0x66 1422 | name = 'fsub' 1423 | 1424 | def execute(self, frame): 1425 | operand_stack = frame.operand_stack 1426 | val1 = operand_stack.pop_float() 1427 | val2 = operand_stack.pop_float() 1428 | res = val1 - val2 1429 | operand_stack.push_float(res) 1430 | 1431 | 1432 | class DSUB(Instruction): 1433 | code = 0x67 1434 | name = 'dsub' 1435 | 1436 | def execute(self, frame): 1437 | operand_stack = frame.operand_stack 1438 | val1 = operand_stack.pop_double() 1439 | val2 = operand_stack.pop_double() 1440 | res = val1 - val2 1441 | operand_stack.push_double(res) 1442 | 1443 | 1444 | class IMUL(Instruction): 1445 | code = 0x68 1446 | name = 'imul' 1447 | 1448 | def execute(self, frame): 1449 | operand_stack = frame.operand_stack 1450 | val1 = operand_stack.pop_int() 1451 | val2 = operand_stack.pop_int() 1452 | res = val1 * val2 1453 | operand_stack.push_int(res) 1454 | 1455 | 1456 | class LMUL(Instruction): 1457 | code = 0x69 1458 | name = 'lmul' 1459 | 1460 | def execute(self, frame): 1461 | operand_stack = frame.operand_stack 1462 | val1 = operand_stack.pop_long() 1463 | val2 = operand_stack.pop_long() 1464 | res = val1 * val2 1465 | operand_stack.push_long(res) 1466 | 1467 | 1468 | class FMUL(Instruction): 1469 | code = 0x6a 1470 | name = 'fmul' 1471 | 1472 | def execute(self, frame): 1473 | operand_stack = frame.operand_stack 1474 | val1 = operand_stack.pop_float() 1475 | val2 = operand_stack.pop_float() 1476 | res = val1 * val2 1477 | operand_stack.push_float(res) 1478 | 1479 | 1480 | class DMUL(Instruction): 1481 | code = 0x6b 1482 | name = 'dmul' 1483 | 1484 | def execute(self, frame): 1485 | operand_stack = frame.operand_stack 1486 | val1 = operand_stack.pop_double() 1487 | val2 = operand_stack.pop_double() 1488 | res = val1 * val2 1489 | operand_stack.push_double(res) 1490 | 1491 | 1492 | class IDIV(Instruction): 1493 | code = 0x6c 1494 | name = 'idiv' 1495 | 1496 | def execute(self, frame): 1497 | operand_stack = frame.operand_stack 1498 | val1 = operand_stack.pop_int() 1499 | val2 = operand_stack.pop_int() 1500 | if val2 == 0: 1501 | error_handler.rise_runtime_error('java.lang.ArithmeticException: x / 0') 1502 | res = val1 / val2 1503 | operand_stack.push_int(res) 1504 | 1505 | 1506 | class LDIV(Instruction): 1507 | code = 0x6d 1508 | name = 'ldiv' 1509 | 1510 | def execute(self, frame): 1511 | operand_stack = frame.operand_stack 1512 | val1 = operand_stack.pop_long() 1513 | val2 = operand_stack.pop_long() 1514 | if val2 == 0: 1515 | error_handler.rise_runtime_error('java.lang.ArithmeticException: x / 0') 1516 | res = val1 / val2 1517 | operand_stack.push_long(res) 1518 | 1519 | 1520 | class FDIV(Instruction): 1521 | code = 0x6e 1522 | name = 'fdiv' 1523 | 1524 | def execute(self, frame): 1525 | # TODO: IEEE 规范中规定的运算规则 1526 | operand_stack = frame.operand_stack 1527 | val1 = operand_stack.pop_float() 1528 | val2 = operand_stack.pop_float() 1529 | res = val1 / val2 1530 | operand_stack.push_float(res) 1531 | 1532 | 1533 | class DDIV(Instruction): 1534 | code = 0x6f 1535 | name = 'ddiv' 1536 | 1537 | def execute(self, frame): 1538 | # TODO: IEEE 规范中规定的运算规则 1539 | operand_stack = frame.operand_stack 1540 | val1 = operand_stack.pop_double() 1541 | val2 = operand_stack.pop_double() 1542 | res = val1 / val2 1543 | operand_stack.push_double(res) 1544 | 1545 | 1546 | class IREM(Instruction): 1547 | code = 0x70 1548 | name = 'irem' 1549 | 1550 | def execute(self, frame): 1551 | operand_stack = frame.operand_stack 1552 | val2 = operand_stack.pop_int() 1553 | val1 = operand_stack.pop_int() 1554 | if val2 == 0: 1555 | error_handler.rise_runtime_error('java.lang.ArithmeticException: x / 0') 1556 | # res = val1 - int(val1 / val2) * val2 1557 | res = val1 % val2 1558 | operand_stack.push_int(res) 1559 | 1560 | 1561 | class LREM(Instruction): 1562 | code = 0x71 1563 | name = 'lrem' 1564 | 1565 | def execute(self, frame): 1566 | operand_stack = frame.operand_stack 1567 | val2 = operand_stack.pop_long() 1568 | val1 = operand_stack.pop_long() 1569 | if val2 == 0: 1570 | error_handler.rise_runtime_error('java.lang.ArithmeticException: x / 0') 1571 | # res = val1 - int(val1 / val2) * val2 1572 | res = val1 % val2 1573 | operand_stack.push_long(res) 1574 | 1575 | 1576 | class FREM(Instruction): 1577 | code = 0x72 1578 | name = 'frem' 1579 | 1580 | def execute(self, frame): 1581 | # TODO: IEEE 规范中规定的运算规则 1582 | operand_stack = frame.operand_stack 1583 | val2 = operand_stack.pop_float() 1584 | val1 = operand_stack.pop_float() 1585 | res = val1 % val2 1586 | operand_stack.push_float(res) 1587 | 1588 | 1589 | class DREM(Instruction): 1590 | code = 0x73 1591 | name = 'drem' 1592 | 1593 | def execute(self, frame): 1594 | # TODO: IEEE 规范中规定的运算规则 1595 | operand_stack = frame.operand_stack 1596 | val2 = operand_stack.pop_double() 1597 | val1 = operand_stack.pop_double() 1598 | res = val1 % val2 1599 | operand_stack.push_double(res) 1600 | 1601 | 1602 | class INEG(Instruction): 1603 | code = 0x74 1604 | name = 'ineg' 1605 | 1606 | def execute(self, frame): 1607 | val = frame.operand_stack.pop_int() 1608 | frame.operand_stack.push_int(-val) 1609 | 1610 | 1611 | class LNEG(Instruction): 1612 | code = 0x75 1613 | name = 'lneg' 1614 | 1615 | def execute(self, frame): 1616 | val = frame.operand_stack.pop_long() 1617 | frame.operand_stack.push_long(-val) 1618 | 1619 | 1620 | class FNEG(Instruction): 1621 | code = 0x76 1622 | name = 'fneg' 1623 | 1624 | def execute(self, frame): 1625 | val = frame.operand_stack.pop_float() 1626 | frame.operand_stack.push_float(-val) 1627 | 1628 | 1629 | class DNEG(Instruction): 1630 | code = 0x77 1631 | name = 'dneg' 1632 | 1633 | def execute(self, frame): 1634 | val = frame.operand_stack.pop_double() 1635 | frame.operand_stack.push_double(-val) 1636 | 1637 | 1638 | class ISHL(Instruction): 1639 | code = 0x78 1640 | name = 'ishl' 1641 | 1642 | def execute(self, frame): 1643 | val2 = frame.operand_stack.pop_int() 1644 | val1 = frame.operand_stack.pop_int() 1645 | s = val2 & 0x1f 1646 | res = val1 << s 1647 | frame.operand_stack.push_int(res) 1648 | 1649 | 1650 | class LSHL(Instruction): 1651 | code = 0x79 1652 | name = 'lshl' 1653 | 1654 | def execute(self, frame): 1655 | val2 = frame.operand_stack.pop_long() 1656 | val1 = frame.operand_stack.pop_long() 1657 | s = val2 & 0x3f 1658 | res = val1 << s 1659 | frame.operand_stack.push_long(res) 1660 | 1661 | 1662 | class ISHR(Instruction): 1663 | code = 0x7a 1664 | name = 'ishr' 1665 | 1666 | def execute(self, frame): 1667 | val2 = frame.operand_stack.pop_int() 1668 | val1 = frame.operand_stack.pop_int() 1669 | s = val2 & 0x1f 1670 | res = val1 >> s 1671 | frame.operand_stack.push_int(res) 1672 | 1673 | 1674 | class LSHR(Instruction): 1675 | code = 0x7b 1676 | name = 'lshr' 1677 | 1678 | def execute(self, frame): 1679 | val2 = frame.operand_stack.pop_long() 1680 | val1 = frame.operand_stack.pop_long() 1681 | s = val2 & 0x3f 1682 | res = val1 >> s 1683 | frame.operand_stack.push_long(res) 1684 | 1685 | 1686 | class IUSHR(Instruction): 1687 | code = 0x7c 1688 | name = 'iushr' 1689 | 1690 | def execute(self, frame): 1691 | val2 = frame.operand_stack.pop_int() 1692 | val1 = frame.operand_stack.pop_int() 1693 | s = val2 & 0x1f 1694 | val = ctypes.c_uint32(val1).value 1695 | res = ctypes.c_int32(val >> s).value 1696 | frame.operand_stack.push_int(res) 1697 | 1698 | 1699 | class LUSHR(Instruction): 1700 | code = 0x7d 1701 | name = 'lushr' 1702 | 1703 | def execute(self, frame): 1704 | val2 = frame.operand_stack.pop_long() 1705 | val1 = frame.operand_stack.pop_long() 1706 | s = val2 & 0x3f 1707 | val = ctypes.c_uint64(val1).value 1708 | res = ctypes.c_int64(val >> s).value 1709 | frame.operand_stack.push_int(res) 1710 | 1711 | 1712 | class IAND(Instruction): 1713 | code = 0x7e 1714 | name = 'iand' 1715 | 1716 | def execute(self, frame): 1717 | val2 = frame.operand_stack.pop_int() 1718 | val1 = frame.operand_stack.pop_int() 1719 | res = val1 & val2 1720 | frame.operand_stack.push_int(res) 1721 | 1722 | 1723 | class LAND(Instruction): 1724 | code = 0x7f 1725 | name = 'land' 1726 | 1727 | def execute(self, frame): 1728 | val2 = frame.operand_stack.pop_long() 1729 | val1 = frame.operand_stack.pop_long() 1730 | res = val1 & val2 1731 | frame.operand_stack.push_long(res) 1732 | 1733 | 1734 | class IOR(Instruction): 1735 | code = 0x80 1736 | name = 'ior' 1737 | 1738 | def execute(self, frame): 1739 | val2 = frame.operand_stack.pop_int() 1740 | val1 = frame.operand_stack.pop_int() 1741 | res = val1 | val2 1742 | frame.operand_stack.push_int(res) 1743 | 1744 | 1745 | class LOR(Instruction): 1746 | code = 0x81 1747 | name = 'lor' 1748 | 1749 | def execute(self, frame): 1750 | val2 = frame.operand_stack.pop_long() 1751 | val1 = frame.operand_stack.pop_long() 1752 | res = val1 | val2 1753 | frame.operand_stack.push_long(res) 1754 | 1755 | 1756 | class IXOR(Instruction): 1757 | code = 0x82 1758 | name = 'ixor' 1759 | 1760 | def execute(self, frame): 1761 | val2 = frame.operand_stack.pop_int() 1762 | val1 = frame.operand_stack.pop_int() 1763 | res = val1 ^ val2 1764 | frame.operand_stack.push_int(res) 1765 | 1766 | 1767 | class LXOR(Instruction): 1768 | code = 0x83 1769 | name = 'lxor' 1770 | 1771 | def execute(self, frame): 1772 | val2 = frame.operand_stack.pop_long() 1773 | val1 = frame.operand_stack.pop_long() 1774 | res = val1 ^ val2 1775 | frame.operand_stack.push_long(res) 1776 | 1777 | 1778 | class INVOKESPECIAL(Instruction): 1779 | code = 0xb7 1780 | name = 'invokespecial' 1781 | 1782 | def __init__(self): 1783 | super(INVOKESPECIAL, self).__init__() 1784 | self.index = -1 1785 | 1786 | def read_operands(self, code_parser): 1787 | index1 = code_parser.read_op() 1788 | index2 = code_parser.read_op() 1789 | self.index = (index1 << 8) | index2 1790 | 1791 | def execute(self, frame): 1792 | # TODO: 方法校验 1793 | constant_pool = frame.method.jclass.constant_pool.constants 1794 | n_method_ref = constant_pool[self.index] 1795 | # TODO: 先忽略基础类的所有方法 1796 | if n_method_ref.class_name == 'java/lang/Object': 1797 | return 1798 | print_utils.print_jvm_status('invokespecial: ' + n_method_ref.name) 1799 | n_method = n_method_ref.resolve_method(frame.method.jclass.class_loader) 1800 | n_frame = Frame(frame.thread, n_method) 1801 | frame.thread.add_frame(n_frame) 1802 | arg_desc = n_method.arg_desc 1803 | i = len(arg_desc) 1804 | for arg in arg_desc: 1805 | if arg == 'I' or arg == 'S' or arg == 'Z' or arg == 'C': 1806 | value = frame.operand_stack.pop_int() 1807 | n_frame.local_vars.add_int(i, value) 1808 | elif arg == 'J': 1809 | value = frame.operand_stack.pop_long() 1810 | n_frame.local_vars.add_long(i, value) 1811 | elif arg == 'F': 1812 | value = frame.operand_stack.pop_float() 1813 | n_frame.local_vars.add_float(i, value) 1814 | elif arg == 'D': 1815 | value = frame.operand_stack.pop_double() 1816 | n_frame.local_vars.add_double(i, value) 1817 | elif arg[0] == 'L': 1818 | jref = frame.operand_stack.pop_ref() 1819 | n_frame.local_vars.add_ref(i, jref) 1820 | i -= 1 1821 | n_frame.local_vars.add_ref(0, frame.operand_stack.pop()) 1822 | 1823 | 1824 | class INVOKEVIRTUAL(Instruction): 1825 | code = 0xb6 1826 | name = 'invokevirtual' 1827 | 1828 | def __init__(self): 1829 | super(INVOKEVIRTUAL, self).__init__() 1830 | self.index = -1 1831 | 1832 | def read_operands(self, code_parser): 1833 | index1 = code_parser.read_op() 1834 | index2 = code_parser.read_op() 1835 | self.index = (index1 << 8) | index2 1836 | 1837 | def execute(self, frame): 1838 | # TODO: 方法校验 1839 | constant_pool = frame.method.jclass.constant_pool.constants 1840 | n_method_ref = constant_pool[self.index] 1841 | # TODO: 先忽略基类的所有方法 1842 | if n_method_ref.class_name == 'java/lang/Object': 1843 | return 1844 | print_utils.print_jvm_status('invokevirtual: ' + n_method_ref.name) 1845 | # 主要是为了获取参数个数 1846 | n_method = n_method_ref.resolve_method_with_super(frame.method.jclass.class_loader) 1847 | arg_desc = n_method.arg_desc 1848 | ref = frame.operand_stack.top(len(arg_desc)) 1849 | if ref is not None: 1850 | real_class_name = ref.handler.obj.jclass.name 1851 | if n_method_ref.class_name != real_class_name: 1852 | n_method = n_method_ref.re_resolve_method_with_super_by_class_name(frame.method.jclass.class_loader, 1853 | real_class_name) 1854 | n_frame = Frame(frame.thread, n_method) 1855 | frame.thread.add_frame(n_frame) 1856 | i = len(arg_desc) 1857 | for arg in arg_desc: 1858 | if arg == 'I' or arg == 'S' or arg == 'Z' or arg == 'C' or arg == 'B': 1859 | value = frame.operand_stack.pop_int() 1860 | n_frame.local_vars.add_int(i, value) 1861 | elif arg == 'J': 1862 | value = frame.operand_stack.pop_long() 1863 | n_frame.local_vars.add_long(i, value) 1864 | elif arg == 'F': 1865 | value = frame.operand_stack.pop_float() 1866 | n_frame.local_vars.add_float(i, value) 1867 | elif arg == 'D': 1868 | value = frame.operand_stack.pop_double() 1869 | n_frame.local_vars.add_double(i, value) 1870 | elif arg[0] == 'L': 1871 | jref = frame.operand_stack.pop_ref() 1872 | n_frame.local_vars.add_ref(i, jref) 1873 | i -= 1 1874 | n_frame.local_vars.add_ref(0, frame.operand_stack.pop()) 1875 | self.__hack(n_frame, n_method) 1876 | 1877 | # 暂时做一些 hack 处理,比如输出 1878 | def __hack(self, n_frame, method): 1879 | # 处理 print 1880 | self.__hack_println(n_frame, method) 1881 | # 处理 thread 1882 | self.__hack_thread(n_frame, method) 1883 | 1884 | def __hack_thread(self, n_frame, method): 1885 | jthis = n_frame.local_vars.get_ref(0) 1886 | if method.name == 'start' and jthis.handler.obj.jclass.super_class_name == 'java/lang/Thread': 1887 | for m in jthis.handler.obj.jclass.methods: 1888 | if m.name == 'run': 1889 | JThread.start_new_thread(m) 1890 | 1891 | def __hack_println(self, n_frame, method): 1892 | if method.name == 'println' and method.jclass.name == 'java/io/PrintStream': 1893 | if method.descriptor == '(Ljava/lang/String;)Ljava/io/PrintStream;': 1894 | jref = n_frame.local_vars.get_ref(1) 1895 | print_utils.StreamPrinter.append_msg(n_frame.thread, jref.data) 1896 | elif method.descriptor == '(I)Ljava/io/PrintStream;': 1897 | jint = n_frame.local_vars.get_int(1) 1898 | print_utils.StreamPrinter.append_msg(n_frame.thread, jint) 1899 | elif method.descriptor == '(S)Ljava/io/PrintStream;': 1900 | jint = n_frame.local_vars.get_int(1) 1901 | print_utils.StreamPrinter.append_msg(n_frame.thread, jint) 1902 | elif method.descriptor == '(B)Ljava/io/PrintStream;': 1903 | jint = n_frame.local_vars.get_int(1) 1904 | print_utils.StreamPrinter.append_msg(n_frame.thread, jint) 1905 | elif method.descriptor == '(C)Ljava/io/PrintStream;': 1906 | jint = n_frame.local_vars.get_int(1) 1907 | print_utils.StreamPrinter.append_msg(n_frame.thread, chr(jint)) 1908 | elif method.descriptor == '(J)Ljava/io/PrintStream;': 1909 | jlong = n_frame.local_vars.get_long(1) 1910 | print_utils.StreamPrinter.append_msg(n_frame.thread, jlong) 1911 | elif method.descriptor == '(D)Ljava/io/PrintStream;': 1912 | jdouble = n_frame.local_vars.get_double(1) 1913 | print_utils.StreamPrinter.append_msg(n_frame.thread, jdouble) 1914 | elif method.descriptor == '(F)Ljava/io/PrintStream;': 1915 | jfloat = n_frame.local_vars.get_float(1) 1916 | print_utils.StreamPrinter.append_msg(n_frame.thread, jfloat) 1917 | elif method.descriptor == '(Z)Ljava/io/PrintStream;': 1918 | jint = n_frame.local_vars.get_int(1) 1919 | if jint == 0: # False 1920 | print_utils.StreamPrinter.append_msg(n_frame.thread, 'false') 1921 | elif jint == 1: # True 1922 | print_utils.StreamPrinter.append_msg(n_frame.thread, 'true') 1923 | else: 1924 | error_handler.rise_runtime_error('runtime error: boolean not true or false') 1925 | 1926 | 1927 | class INVOKESTATIC(Instruction): 1928 | code = 0xb8 1929 | name = 'invokestatic' 1930 | 1931 | def __init__(self): 1932 | super(INVOKESTATIC, self).__init__() 1933 | self.index = -1 1934 | 1935 | def read_operands(self, code_parser): 1936 | index1 = code_parser.read_op() 1937 | index2 = code_parser.read_op() 1938 | self.index = (index1 << 8) | index2 1939 | 1940 | def execute(self, frame): 1941 | # TODO: 方法校验 1942 | constant_pool = frame.method.jclass.constant_pool.constants 1943 | n_method_ref = constant_pool[self.index] 1944 | print_utils.print_jvm_status('invokestatic: ' + n_method_ref.name) 1945 | n_method = n_method_ref.resolve_method(frame.method.jclass.class_loader) 1946 | n_frame = Frame(frame.thread, n_method) 1947 | frame.thread.add_frame(n_frame) 1948 | arg_desc = n_method.arg_desc 1949 | i = len(arg_desc) 1950 | for arg in arg_desc: 1951 | i -= 1 1952 | if arg == 'I' or arg == 'S' or arg == 'Z' or arg == 'C': 1953 | value = frame.operand_stack.pop_int() 1954 | n_frame.local_vars.add_int(i, value) 1955 | elif arg == 'J': 1956 | value = frame.operand_stack.pop_long() 1957 | n_frame.local_vars.add_long(i, value) 1958 | elif arg == 'F': 1959 | value = frame.operand_stack.pop_float() 1960 | n_frame.local_vars.add_float(i, value) 1961 | elif arg == 'D': 1962 | value = frame.operand_stack.pop_double() 1963 | n_frame.local_vars.add_double(i, value) 1964 | elif arg[0] == 'L': 1965 | jref = frame.operand_stack.pop_ref() 1966 | n_frame.local_vars.add_ref(i, jref) 1967 | 1968 | 1969 | class IRETURN(Instruction): 1970 | code = 0xac 1971 | name = 'ireturn' 1972 | 1973 | def execute(self, frame): 1974 | frame.thread.pop_frame() 1975 | r_value = frame.operand_stack.pop_int() 1976 | c_frame = frame.thread.top_frame() 1977 | c_frame.operand_stack.push_int(r_value) 1978 | 1979 | 1980 | class LRETURN(Instruction): 1981 | code = 0xad 1982 | name = 'lreturn' 1983 | 1984 | def execute(self, frame): 1985 | frame.thread.pop_frame() 1986 | r_value = frame.operand_stack.pop_long() 1987 | c_frame = frame.thread.top_frame() 1988 | c_frame.operand_stack.push_long(r_value) 1989 | 1990 | 1991 | class FRETURN(Instruction): 1992 | code = 0xae 1993 | name = 'freturn' 1994 | 1995 | def execute(self, frame): 1996 | frame.thread.pop_frame() 1997 | r_value = frame.operand_stack.pop_float() 1998 | c_frame = frame.thread.top_frame() 1999 | c_frame.operand_stack.push_float(r_value) 2000 | 2001 | 2002 | class DRETURN(Instruction): 2003 | code = 0xaf 2004 | name = 'dreturn' 2005 | 2006 | def execute(self, frame): 2007 | frame.thread.pop_frame() 2008 | r_value = frame.operand_stack.pop_double() 2009 | c_frame = frame.thread.top_frame() 2010 | c_frame.operand_stack.push_double(r_value) 2011 | 2012 | 2013 | class ARETURN(Instruction): 2014 | code = 0xb0 2015 | name = 'areturn' 2016 | 2017 | def execute(self, frame): 2018 | frame.thread.pop_frame() 2019 | r_value = frame.operand_stack.pop_ref() 2020 | c_frame = frame.thread.top_frame() 2021 | c_frame.operand_stack.push_ref(r_value) 2022 | 2023 | 2024 | class ISTORE_N(Instruction): 2025 | @abc.abstractmethod 2026 | def get_index(self): 2027 | pass 2028 | 2029 | def execute(self, frame): 2030 | value = frame.operand_stack.pop_int() 2031 | index = self.get_index() 2032 | frame.local_vars.add_int(index, value) 2033 | 2034 | 2035 | class ISTORE(ISTORE_N): 2036 | code = 0x36 2037 | name = 'istore' 2038 | 2039 | def __init__(self): 2040 | super(ISTORE, self).__init__() 2041 | self.index = 0 2042 | 2043 | def read_operands(self, code_parser): 2044 | self.index = code_parser.read_op() 2045 | 2046 | def get_index(self): 2047 | return self.index 2048 | 2049 | 2050 | class ISTORE_0(ISTORE_N): 2051 | code = 0x3b 2052 | name = 'istore_0' 2053 | 2054 | def get_index(self): 2055 | return 0 2056 | 2057 | 2058 | class ISTORE_1(ISTORE_N): 2059 | code = 0x3c 2060 | name = 'istore_1' 2061 | 2062 | def get_index(self): 2063 | return 1 2064 | 2065 | 2066 | class ISTORE_2(ISTORE_N): 2067 | code = 0x3d 2068 | name = 'istore_2' 2069 | 2070 | def get_index(self): 2071 | return 2 2072 | 2073 | 2074 | class ISTORE_3(ISTORE_N): 2075 | code = 0x3e 2076 | name = 'istore_3' 2077 | 2078 | def get_index(self): 2079 | return 3 2080 | 2081 | 2082 | class DSTORE_N(Instruction): 2083 | @abc.abstractmethod 2084 | def get_index(self): 2085 | pass 2086 | 2087 | def execute(self, frame): 2088 | value = frame.operand_stack.pop_double() 2089 | index = self.get_index() 2090 | frame.local_vars.add_double(index, value) 2091 | 2092 | 2093 | class DSTORE(DSTORE_N): 2094 | code = 0x39 2095 | name = 'dstore' 2096 | 2097 | def __init__(self): 2098 | super(DSTORE, self).__init__() 2099 | self.index = 0 2100 | 2101 | def read_operands(self, code_parser): 2102 | self.index = code_parser.read_op() 2103 | 2104 | def get_index(self): 2105 | return self.index 2106 | 2107 | 2108 | class DSTORE_0(DSTORE_N): 2109 | code = 0x47 2110 | name = 'dstore_0' 2111 | 2112 | def get_index(self): 2113 | return 0 2114 | 2115 | 2116 | class DSTORE_1(DSTORE_N): 2117 | code = 0x48 2118 | name = 'dstore_1' 2119 | 2120 | def get_index(self): 2121 | return 1 2122 | 2123 | 2124 | class DSTORE_2(DSTORE_N): 2125 | code = 0x49 2126 | name = 'dstore_2' 2127 | 2128 | def get_index(self): 2129 | return 2 2130 | 2131 | 2132 | class DSTORE_3(DSTORE_N): 2133 | code = 0x4a 2134 | name = 'dstore_3' 2135 | 2136 | def get_index(self): 2137 | return 3 2138 | 2139 | 2140 | class FSTORE_N(Instruction): 2141 | @abc.abstractmethod 2142 | def get_index(self): 2143 | pass 2144 | 2145 | def execute(self, frame): 2146 | value = frame.operand_stack.pop_float() 2147 | index = self.get_index() 2148 | frame.local_vars.add_float(index, value) 2149 | 2150 | 2151 | class FSTORE(FSTORE_N): 2152 | code = 0x38 2153 | name = 'fstore' 2154 | 2155 | def __init__(self): 2156 | super(FSTORE, self).__init__() 2157 | self.index = 0 2158 | 2159 | def read_operands(self, code_parser): 2160 | self.index = code_parser.read_op() 2161 | 2162 | def get_index(self): 2163 | return self.index 2164 | 2165 | 2166 | class FSTORE_0(FSTORE_N): 2167 | code = 0x43 2168 | name = 'fstore_0' 2169 | 2170 | def get_index(self): 2171 | return 0 2172 | 2173 | 2174 | class FSTORE_1(FSTORE_N): 2175 | code = 0x44 2176 | name = 'fstore_1' 2177 | 2178 | def get_index(self): 2179 | return 1 2180 | 2181 | 2182 | class FSTORE_2(FSTORE_N): 2183 | code = 0x45 2184 | name = 'fstore_2' 2185 | 2186 | def get_index(self): 2187 | return 2 2188 | 2189 | 2190 | class FSTORE_3(FSTORE_N): 2191 | code = 0x46 2192 | name = 'fstore_3' 2193 | 2194 | def get_index(self): 2195 | return 3 2196 | 2197 | 2198 | class LSTORE_N(Instruction): 2199 | @abc.abstractmethod 2200 | def get_index(self): 2201 | pass 2202 | 2203 | def execute(self, frame): 2204 | value = frame.operand_stack.pop_long() 2205 | index = self.get_index() 2206 | frame.local_vars.add_long(index, value) 2207 | 2208 | 2209 | class LSTORE(LSTORE_N): 2210 | code = 0x37 2211 | name = 'lstore' 2212 | 2213 | def __init__(self): 2214 | super(LSTORE, self).__init__() 2215 | self.index = 0 2216 | 2217 | def read_operands(self, code_parser): 2218 | self.index = code_parser.read_op() 2219 | 2220 | def get_index(self): 2221 | return self.index 2222 | 2223 | 2224 | class LSTORE_0(LSTORE_N): 2225 | code = 0x3f 2226 | name = 'lstore_0' 2227 | 2228 | def get_index(self): 2229 | return 0 2230 | 2231 | 2232 | class LSTORE_1(LSTORE_N): 2233 | code = 0x40 2234 | name = 'lstore_1' 2235 | 2236 | def get_index(self): 2237 | return 1 2238 | 2239 | 2240 | class LSTORE_2(LSTORE_N): 2241 | code = 0x41 2242 | name = 'lstore_2' 2243 | 2244 | def get_index(self): 2245 | return 2 2246 | 2247 | 2248 | class LSTORE_3(LSTORE_N): 2249 | code = 0x42 2250 | name = 'lstore_3' 2251 | 2252 | def get_index(self): 2253 | return 3 2254 | 2255 | 2256 | class LDC(Instruction): 2257 | code = 0x12 2258 | name = 'ldc' 2259 | 2260 | def __init__(self): 2261 | super(LDC, self).__init__() 2262 | self.index = None 2263 | 2264 | def read_operands(self, code_parser): 2265 | self.index = code_parser.read_op() 2266 | 2267 | def execute(self, frame): 2268 | constants = frame.method.jclass.constant_pool.constants 2269 | ref = constants[self.index] 2270 | operand_stack = frame.operand_stack 2271 | if isinstance(ref, JInteger): 2272 | operand_stack.push_int(ref.data) 2273 | elif isinstance(ref, JFloat): 2274 | operand_stack.push_float(ref.data) 2275 | elif isinstance(ref, JString): 2276 | operand_stack.push_ref(ref) 2277 | elif isinstance(ref, JRef): 2278 | operand_stack.push_ref(ref) 2279 | else: 2280 | operand_stack.push(None) 2281 | 2282 | 2283 | class LDC_W(LDC): 2284 | code = 0x13 2285 | name = 'ldc_w' 2286 | 2287 | def read_operands(self, code_parser): 2288 | index1 = code_parser.read_op() 2289 | index2 = code_parser.read_op() 2290 | self.index = (index1 << 8) | index2 2291 | 2292 | 2293 | class LDC2_W(Instruction): 2294 | code = 0x14 2295 | name = 'ldc2_w' 2296 | 2297 | def __init__(self): 2298 | super(LDC2_W, self).__init__() 2299 | self.index = None 2300 | 2301 | def read_operands(self, code_parser): 2302 | index1 = code_parser.read_op() 2303 | index2 = code_parser.read_op() 2304 | self.index = (index1 << 8) | index2 2305 | 2306 | def execute(self, frame): 2307 | constants = frame.method.jclass.constant_pool.constants 2308 | ref = constants[self.index] 2309 | operand_stack = frame.operand_stack 2310 | if isinstance(ref, JLong): 2311 | operand_stack.push_long(ref.data) 2312 | elif isinstance(ref, JDouble): 2313 | operand_stack.push_double(ref.data) 2314 | elif isinstance(ref, JString): 2315 | operand_stack.push_ref(ref) 2316 | else: # TODO: Class 对象 2317 | pass 2318 | 2319 | 2320 | class NOP(Instruction): 2321 | code = 0x00 2322 | name = 'nop' 2323 | 2324 | def execute(self, frame): 2325 | pass 2326 | 2327 | 2328 | class IF_COND(JUMP_INC): 2329 | def __init__(self): 2330 | super(IF_COND, self).__init__() 2331 | self.branch = 0 2332 | 2333 | @abc.abstractmethod 2334 | def compare(self, value): 2335 | pass 2336 | 2337 | def read_operands(self, code_parser): 2338 | branch1 = code_parser.read_op() 2339 | branch2 = code_parser.read_op() 2340 | self.branch = common_utils.get_short_from_bytes(branch1, branch2) 2341 | 2342 | def execute(self, frame): 2343 | value = frame.operand_stack.pop_int() 2344 | if self.compare(value): 2345 | self.jump_by(frame, self.branch) 2346 | 2347 | 2348 | class IFEQ(IF_COND): 2349 | code = 0x99 2350 | name = 'ifeq' 2351 | 2352 | def compare(self, value): 2353 | return value == 0 2354 | 2355 | 2356 | class IFNE(IF_COND): 2357 | code = 0x9a 2358 | name = 'ifne' 2359 | 2360 | def compare(self, value): 2361 | return value != 0 2362 | 2363 | 2364 | class IFLT(IF_COND): 2365 | code = 0x9b 2366 | name = 'iflt' 2367 | 2368 | def compare(self, value): 2369 | return value < 0 2370 | 2371 | 2372 | class IFGE(IF_COND): 2373 | code = 0x9c 2374 | name = 'ifge' 2375 | 2376 | def compare(self, value): 2377 | return value >= 0 2378 | 2379 | 2380 | class IFGT(IF_COND): 2381 | code = 0x9d 2382 | name = 'ifgt' 2383 | 2384 | def compare(self, value): 2385 | return value > 0 2386 | 2387 | 2388 | class IFLE(IF_COND): 2389 | code = 0x9e 2390 | name = 'ifle' 2391 | 2392 | def compare(self, value): 2393 | return value <= 0 2394 | 2395 | 2396 | class IF_ICMP_COND(JUMP_INC): 2397 | def __init__(self): 2398 | super(IF_ICMP_COND, self).__init__() 2399 | self.branch = 0 2400 | 2401 | @abc.abstractmethod 2402 | def compare(self, value1, value2): 2403 | pass 2404 | 2405 | def read_operands(self, code_parser): 2406 | branch1 = code_parser.read_op() 2407 | branch2 = code_parser.read_op() 2408 | self.branch = common_utils.get_short_from_bytes(branch1, branch2) 2409 | 2410 | def execute(self, frame): 2411 | value2 = frame.operand_stack.pop_int() 2412 | value1 = frame.operand_stack.pop_int() 2413 | if self.compare(value1, value2): 2414 | self.jump_by(frame, self.branch) 2415 | 2416 | 2417 | class IF_ICMPEQ(IF_ICMP_COND): 2418 | code = 0x9f 2419 | name = 'if_icmpeq' 2420 | 2421 | def compare(self, value1, value2): 2422 | return value1 == value2 2423 | 2424 | 2425 | class IF_ICMPNE(IF_ICMP_COND): 2426 | code = 0xa0 2427 | name = 'if_icmpne' 2428 | 2429 | def compare(self, value1, value2): 2430 | return value1 != value2 2431 | 2432 | 2433 | class IF_ICMPLT(IF_ICMP_COND): 2434 | code = 0xa1 2435 | name = 'if_icmplt' 2436 | 2437 | def compare(self, value1, value2): 2438 | return value1 < value2 2439 | 2440 | 2441 | class IF_ICMPGE(IF_ICMP_COND): 2442 | code = 0xa2 2443 | name = 'if_icmpge' 2444 | 2445 | def compare(self, value1, value2): 2446 | return value1 >= value2 2447 | 2448 | 2449 | class IF_ICMPGT(IF_ICMP_COND): 2450 | code = 0xa3 2451 | name = 'if_icmpgt' 2452 | 2453 | def compare(self, value1, value2): 2454 | return value1 > value2 2455 | 2456 | 2457 | class IF_ICMPLE(IF_ICMP_COND): 2458 | code = 0xa4 2459 | name = 'if_icmple' 2460 | 2461 | def compare(self, value1, value2): 2462 | return value1 <= value2 2463 | 2464 | 2465 | class IF_ACMP_COND(JUMP_INC): 2466 | def __init__(self): 2467 | super(IF_ACMP_COND, self).__init__() 2468 | self.branch = 0 2469 | 2470 | @abc.abstractmethod 2471 | def compare(self, ref1, ref2): 2472 | pass 2473 | 2474 | def read_operands(self, code_parser): 2475 | branch1 = code_parser.read_op() 2476 | branch2 = code_parser.read_op() 2477 | self.branch = common_utils.get_short_from_bytes(branch1, branch2) 2478 | 2479 | def execute(self, frame): 2480 | # TODO: ref 怎么做比较? 2481 | value2 = frame.operand_stack.pop_ref() 2482 | value1 = frame.operand_stack.pop_ref() 2483 | if self.compare(value1, value2): 2484 | self.jump_by(frame, self.branch) 2485 | 2486 | 2487 | class IF_ACMPEQ(IF_ACMP_COND): 2488 | code = 0xa5 2489 | name = 'if_acmpeq' 2490 | 2491 | def compare(self, ref1, ref2): 2492 | return ref1 == ref2 2493 | 2494 | 2495 | class IF_ACMPNE(IF_ACMP_COND): 2496 | code = 0xa6 2497 | name = 'if_acmpne' 2498 | 2499 | def compare(self, ref1, ref2): 2500 | return ref1 != ref2 2501 | 2502 | 2503 | # impdep1 impdep2 breakpoint 为保留操作符 2504 | class IMPDEP1(Instruction): 2505 | code = 0xfe 2506 | name = 'impdep1' 2507 | 2508 | def execute(self, frame): 2509 | pass 2510 | 2511 | 2512 | class IMPDEP2(Instruction): 2513 | code = 0xff 2514 | name = 'impdep2' 2515 | 2516 | def execute(self, frame): 2517 | pass 2518 | 2519 | 2520 | class Breakpoint(Instruction): 2521 | code = 0xca 2522 | name = 'breakpoint' 2523 | 2524 | def execute(self, frame): 2525 | pass 2526 | 2527 | 2528 | class NEW(Instruction): 2529 | code = 0xbb 2530 | name = 'new' 2531 | 2532 | def __init__(self): 2533 | super(NEW, self).__init__() 2534 | self.index = -1 2535 | 2536 | def read_operands(self, code_parser): 2537 | index1 = code_parser.read_op() 2538 | index2 = code_parser.read_op() 2539 | self.index = (index1 << 8) | index2 2540 | 2541 | def execute(self, frame): 2542 | class_loader = frame.method.jclass.class_loader 2543 | if class_loader is None: 2544 | class_loader = ClassLoader() 2545 | frame.method.jclass.class_loader = class_loader 2546 | constant_pool = frame.method.jclass.constant_pool 2547 | ref = constant_pool.constants[self.index] 2548 | jclass = class_loader.load_class(ref.class_name) 2549 | ref = JRef.new_object(jclass) # JObject.new_object() 返回的是真实实例对象 JRef.new_object() 返回的是引用,并且会吧 object 放入 gc 堆 2550 | frame.operand_stack.push_ref(ref) 2551 | 2552 | 2553 | class NEWARRAY(Instruction): 2554 | code = 0xbc 2555 | name = 'newarray' 2556 | 2557 | def __init__(self): 2558 | self.atype = None 2559 | 2560 | def read_operands(self, code_parser): 2561 | self.atype = code_parser.read_op() 2562 | 2563 | def execute(self, frame): 2564 | count = frame.operand_stack.pop_int() 2565 | class_loader = frame.method.jclass.class_loader 2566 | if class_loader is None: 2567 | class_loader = ClassLoader() 2568 | frame.method.jclass.class_loader = class_loader 2569 | jclass = class_loader.load_class(JArray.get_array_jclass_name(self.atype)) 2570 | jref = JRef.new_array(jclass, self.atype, count) 2571 | frame.operand_stack.push_ref(jref) 2572 | 2573 | 2574 | class ANEWARRAY(Instruction): 2575 | code = 0xbd 2576 | name = 'anewarray' 2577 | 2578 | def __init__(self): 2579 | super(ANEWARRAY, self).__init__() 2580 | self.index = 0 2581 | 2582 | def read_operands(self, code_parser): 2583 | index1 = code_parser.read_op() 2584 | index2 = code_parser.read_op() 2585 | self.index = (index1 << 8) | index2 2586 | 2587 | def execute(self, frame): 2588 | count = frame.operand_stack.pop_int() 2589 | class_loader = frame.method.jclass.class_loader 2590 | if class_loader is None: 2591 | class_loader = ClassLoader() 2592 | frame.method.jclass.class_loader = class_loader 2593 | clref = frame.method.jclass.constant_pool.constants[self.index] 2594 | jclass = class_loader.load_class(JArray.get_ref_array_jclass_name(clref.class_name)) 2595 | jref = JRef.new_ref_array(jclass, clref, count) 2596 | frame.operand_stack.push_ref(jref) 2597 | 2598 | 2599 | class ARRAY_LENGTH(Instruction): 2600 | code = 0xbe 2601 | name = 'arraylength' 2602 | 2603 | def execute(self, frame): 2604 | ref = frame.operand_stack.pop_ref() 2605 | InsUtils.check_ref_null(ref) 2606 | if ref.handler.obj is None: 2607 | error_handler.rise_null_point_error() 2608 | obj = ref.handler.obj 2609 | if not isinstance(ref.handler.obj, JArray): 2610 | error_handler.rise_runtime_error('!!! not array !!!') 2611 | frame.operand_stack.push_int(obj.length) 2612 | 2613 | 2614 | class POP(Instruction): 2615 | code = 0x57 2616 | name = 'pop' 2617 | 2618 | def execute(self, frame): 2619 | frame.operand_stack.pop_raw() 2620 | 2621 | 2622 | class POP2(Instruction): 2623 | code = 0x58 2624 | name = 'pop2' 2625 | 2626 | def execute(self, frame): 2627 | frame.operand_stack.pop() 2628 | if frame.operand_stack.is_top_type1(): 2629 | frame.operand_stack.pop() 2630 | 2631 | 2632 | class PUTFIELD(Instruction): 2633 | code = 0xb5 2634 | name = 'putfield' 2635 | 2636 | def __init__(self): 2637 | super(PUTFIELD, self).__init__() 2638 | self.index = 0 2639 | 2640 | def read_operands(self, code_parser): 2641 | index1 = code_parser.read_op() 2642 | index2 = code_parser.read_op() 2643 | self.index = (index1 << 8) | index2 2644 | 2645 | @staticmethod 2646 | def check_state(frame, field_ref, cl_ref): 2647 | if field_ref.is_static(): 2648 | error_handler.rise_runtime_error('java.lang.IncompatibleClassChangeError: put field to static value') 2649 | if field_ref.is_final() and frame.method.name != '': 2650 | error_handler.rise_runtime_error('java.lang.IllegalAccessError: val is final') 2651 | if cl_ref is None or cl_ref.handler is None or cl_ref.handler.obj is None: 2652 | error_handler.rise_runtime_error('java.lang.NullPointerException ref is null') 2653 | 2654 | def execute(self, frame): 2655 | # TODO: field 验证 2656 | field_ref = frame.method.jclass.constant_pool.constants[self.index] 2657 | val = frame.operand_stack.pop() 2658 | cl_ref = frame.operand_stack.pop_ref() 2659 | PUTFIELD.check_state(frame, field_ref, cl_ref) 2660 | if isinstance(val, JRef): 2661 | InsUtils.check_ref_null(cl_ref) 2662 | cl_ref.handler.obj.put_ref_field(field_ref.name, val) 2663 | else: 2664 | cl_ref.handler.obj.put_field(field_ref.name, val) 2665 | 2666 | 2667 | class GETFIELD(Instruction): 2668 | code = 0xb4 2669 | name = 'getfield' 2670 | 2671 | def __init__(self): 2672 | super(GETFIELD, self).__init__() 2673 | self.index = 0 2674 | 2675 | def read_operands(self, code_parser): 2676 | index1 = code_parser.read_op() 2677 | index2 = code_parser.read_op() 2678 | self.index = (index1 << 8) | index2 2679 | 2680 | def execute(self, frame): 2681 | fieldref = frame.method.jclass.constant_pool.constants[self.index] 2682 | clref = frame.operand_stack.pop_ref() 2683 | InsUtils.check_ref_null(clref) 2684 | InsUtils.check_ref_null(clref) 2685 | val = clref.handler.obj.get_field(fieldref.name) 2686 | ftype = InsUtils.get_type_by_descriptor(fieldref.descriptor) 2687 | if ftype == InsUtils.TYPE_INT: 2688 | frame.operand_stack.push_int(val) 2689 | elif ftype == InsUtils.TYPE_FLOAT: 2690 | frame.operand_stack.push_float(val) 2691 | elif ftype == InsUtils.TYPE_LONG: 2692 | frame.operand_stack.push_long(val) 2693 | elif ftype == InsUtils.TYPE_DOUBLE: 2694 | frame.operand_stack.push_double(val) 2695 | elif ftype == InsUtils.TYPE_REF or ftype == InsUtils.TYPE_ARRAY: 2696 | frame.operand_stack.push_ref(val) 2697 | 2698 | 2699 | class RETURN(Instruction): 2700 | code = 0xb1 2701 | name = 'return' 2702 | 2703 | def __init__(self): 2704 | super(RETURN, self).__init__() 2705 | 2706 | def execute(self, frame): 2707 | frame.thread.pop_frame() 2708 | 2709 | 2710 | class SIPUSH(Instruction): 2711 | code = 0x11 2712 | name = 'sipush' 2713 | 2714 | def __init__(self): 2715 | super(SIPUSH, self).__init__() 2716 | self.byte = 0 2717 | 2718 | def read_operands(self, code_parser): 2719 | byte1 = code_parser.read_op() 2720 | byte2 = code_parser.read_op() 2721 | self.byte = (byte1 << 8) | byte2 2722 | 2723 | def execute(self, frame): 2724 | frame.operand_stack.push_int(ctypes.c_short(self.byte).value) 2725 | 2726 | 2727 | class SWAP(Instruction): 2728 | code = 0x5f 2729 | name = 'swap' 2730 | 2731 | def execute(self, frame): 2732 | value1 = frame.operand_stack.pop() 2733 | 2734 | 2735 | class TABLE_SWITCH(JUMP_INC): 2736 | code = 0xaa 2737 | name = 'tableswitch' 2738 | 2739 | def __init__(self): 2740 | super(TABLE_SWITCH, self).__init__() 2741 | self.default = 0 2742 | self.low = 0 2743 | self.high = 0 2744 | self.count = 0 2745 | self.offsets = [] 2746 | 2747 | def read_operands(self, code_parser): 2748 | code_parser.skip_padding() 2749 | 2750 | self.default = code_parser.read_4byte() 2751 | 2752 | self.low = code_parser.read_4byte() 2753 | 2754 | self.high = code_parser.read_4byte() 2755 | 2756 | self.count = self.high - self.low + 1 2757 | 2758 | for i in range(self.count): 2759 | offset = code_parser.read_4byte() 2760 | self.offsets.append(offset) 2761 | 2762 | def execute(self, frame): 2763 | index = frame.operand_stack.pop_int() 2764 | if index < self.low or index > self.high: 2765 | self.jump_by(frame, self.default) 2766 | else: 2767 | self.jump_by(frame, self.offsets[index - self.low]) 2768 | 2769 | 2770 | class LOOK_UP_SWITCH(JUMP_INC): 2771 | code = 0xab 2772 | name = 'lookupswitch' 2773 | 2774 | def __init__(self): 2775 | super(LOOK_UP_SWITCH, self).__init__() 2776 | self.default = 0 2777 | self.npairs = 0 2778 | self.pairs = {} 2779 | 2780 | def read_operands(self, code_parser): 2781 | code_parser.skip_padding() 2782 | 2783 | self.default = code_parser.read_4byte() 2784 | self.npairs = code_parser.read_4byte() 2785 | 2786 | for i in range(self.npairs): 2787 | match = code_parser.read_4byte() 2788 | offset = code_parser.read_4byte() 2789 | self.pairs[match] = offset 2790 | 2791 | def execute(self, frame): 2792 | pairs = self.pairs 2793 | key = frame.operand_stack.pop_int() 2794 | if key in pairs: 2795 | self.jump_by(frame, pairs[key]) 2796 | else: 2797 | self.jump_by(frame, self.default) 2798 | 2799 | 2800 | class CHECK_CAST(Instruction): 2801 | code = 0xc0 2802 | name = 'checkcast' 2803 | 2804 | def __init__(self): 2805 | super(CHECK_CAST, self).__init__() 2806 | self.index = 0 2807 | 2808 | def read_operands(self, code_parser): 2809 | index1 = code_parser.read_op() 2810 | index2 = code_parser.read_op() 2811 | self.index = (index1 << 8) | index2 2812 | 2813 | def execute(self, frame): 2814 | # TODO: interface 实现 2815 | ref = frame.operand_stack.top() 2816 | if not isinstance(ref, JRef): 2817 | error_handler.rise_runtime_error('checkcast param must be ref') 2818 | cl_ref = frame.method.jclass.constant_pool.constants[self.index] 2819 | name = cl_ref.class_name 2820 | cast_class = ref.handler.obj.jclass 2821 | while cast_class is not None: 2822 | if cast_class.name == name: 2823 | return 2824 | cast_class = cast_class.super_class 2825 | error_handler.rise_class_cast_error() 2826 | 2827 | 2828 | class INSTANCE_OF(Instruction): 2829 | code = 0xc1 2830 | name = 'instanceof' 2831 | 2832 | def __init__(self): 2833 | super(INSTANCE_OF, self).__init__() 2834 | self.index = 0 2835 | 2836 | def read_operands(self, code_parser): 2837 | index1 = code_parser.read_op() 2838 | index2 = code_parser.read_op() 2839 | self.index = (index1 << 8) | index2 2840 | 2841 | def execute(self, frame): 2842 | # TODO: interface 实现 2843 | ref = frame.operand_stack.top() 2844 | if not isinstance(ref, JRef): 2845 | error_handler.rise_runtime_error('instance param must be ref') 2846 | cl_ref = frame.method.jclass.constant_pool.constants[self.index] 2847 | name = cl_ref.class_name 2848 | if ref.handler is None: 2849 | frame.operand_stack.push_int(0) 2850 | return 2851 | cast_class = ref.handler.obj.jclass 2852 | while cast_class is not None: 2853 | if cast_class.name == name: 2854 | frame.operand_stack.push_int(1) 2855 | return 2856 | cast_class = cast_class.super_class 2857 | frame.operand_stack.push_int(0) 2858 | 2859 | 2860 | class WIDE(Instruction): 2861 | code = 0xc4 2862 | name = 'wide' 2863 | 2864 | def __init__(self): 2865 | super(WIDE, self).__init__() 2866 | self.code = None 2867 | self.index = 0 2868 | self.const = 0 2869 | self.ins = None 2870 | self.type1_code_map = { 2871 | ILOAD.code: ILOAD, 2872 | FLOAD.code: FLOAD, 2873 | ALOAD.code: ALOAD, 2874 | LLOAD.code: LLOAD, 2875 | DLOAD.code: DLOAD, 2876 | ISTORE.code: ISTORE, 2877 | FSTORE.code: FSTORE, 2878 | ASTORE.code: ASTORE, 2879 | LSTORE.code: LSTORE, 2880 | DSTORE.code: DSTORE, 2881 | } 2882 | self.type2_code_map = { 2883 | IINC.code: IINC 2884 | } 2885 | 2886 | def read_operands(self, code_parser): 2887 | self.code = code_parser.read_op() 2888 | index1 = code_parser.read_op() 2889 | index2 = code_parser.read_op() 2890 | self.index = (index1 << 8) | index2 2891 | if self.code in self.type1_code_map: 2892 | ins = self.type1_code_map[self.code]() 2893 | ins.index = self.index 2894 | self.ins = ins 2895 | elif self.code in self.type2_code_map: 2896 | ins = self.type2_code_map[self.code]() 2897 | ins.index = self.index 2898 | const1 = code_parser.read_op() 2899 | const2 = code_parser.read_op() 2900 | self.const = (const1 << 8) | const2 2901 | ins.const = self.const 2902 | self.ins = ins 2903 | 2904 | def execute(self, frame): 2905 | self.ins.execute(frame) 2906 | 2907 | 2908 | class IF_NULL(JUMP_INC): 2909 | code = 0xc6 2910 | name = 'ifnull' 2911 | 2912 | def __init__(self): 2913 | super(IF_NULL, self).__init__() 2914 | self.branch = 0 2915 | 2916 | def read_operands(self, code_parser): 2917 | branch1 = code_parser.read_op() 2918 | branch2 = code_parser.read_op() 2919 | self.branch = (branch1 << 8) | branch2 2920 | 2921 | def execute(self, frame): 2922 | ref = frame.operand_stack.pop_ref() 2923 | if ref is None or ref.handler is None or ref.handler.obj is None: 2924 | self.jump_by(frame, self.branch) 2925 | 2926 | 2927 | class IF_NON_NULL(JUMP_INC): 2928 | code = 0xc7 2929 | name = 'ifnonnull' 2930 | 2931 | def __init__(self): 2932 | super(IF_NON_NULL, self).__init__() 2933 | self.branch = 0 2934 | 2935 | def read_operands(self, code_parser): 2936 | branch1 = code_parser.read_op() 2937 | branch2 = code_parser.read_op() 2938 | self.branch = (branch1 << 8) | branch2 2939 | 2940 | def execute(self, frame): 2941 | ref = frame.operand_stack.pop_ref() 2942 | if ref is not None and ref.handler is not None and ref.handler.obj is not None: 2943 | self.jump_by(frame, self.branch) 2944 | 2945 | 2946 | class ATHROW(JUMP_INC): 2947 | code = 0xbf 2948 | name = 'athrow' 2949 | 2950 | def execute(self, frame): 2951 | thread = frame.thread 2952 | ref = frame.operand_stack.pop_ref() 2953 | exceptions = frame.method.exceptions 2954 | InsUtils.check_ref_null(ref) 2955 | catched = False 2956 | while exceptions is not None: 2957 | for ex in exceptions: 2958 | cl_ref = frame.method.jclass.constant_pool.constants[ex.catch_type] 2959 | jclass = ref.handler.obj.jclass 2960 | while jclass is not None and jclass.name != 'java/lang/Object': 2961 | if cl_ref.class_name == jclass.name: 2962 | frame.operand_stack.clear() 2963 | frame.operand_stack.push_ref(ref) 2964 | self.jump_to(frame, ex.handler_pc) 2965 | catched = True 2966 | break 2967 | jclass = jclass.super_class 2968 | if catched: 2969 | break 2970 | if catched: 2971 | break 2972 | thread.pop_frame() 2973 | if not thread.has_frame(): 2974 | break 2975 | frame = thread.top_frame() 2976 | exceptions = frame.method.exceptions 2977 | if not catched: 2978 | error_handler.rise_runtime_error('none catched exception: ' + ref.handler.obj.jclass.name) 2979 | 2980 | 2981 | instruction_cache = dict() 2982 | 2983 | 2984 | def register_instruction(ins): 2985 | instruction_cache[ins.code] = ins 2986 | 2987 | 2988 | register_instruction(NOP) 2989 | register_instruction(ACONST_NULL) 2990 | register_instruction(ALOAD) 2991 | register_instruction(ALOAD_0) 2992 | register_instruction(ALOAD_1) 2993 | register_instruction(ALOAD_2) 2994 | register_instruction(ALOAD_3) 2995 | register_instruction(ASTORE) 2996 | register_instruction(ASTORE_0) 2997 | register_instruction(ASTORE_1) 2998 | register_instruction(ASTORE_2) 2999 | register_instruction(ASTORE_3) 3000 | register_instruction(ARETURN) 3001 | register_instruction(BIPUSH) 3002 | register_instruction(DUP) 3003 | register_instruction(DUP_X1) 3004 | register_instruction(DUP_X2) 3005 | register_instruction(DUP2) 3006 | register_instruction(DUP2_X1) 3007 | register_instruction(DUP2_X2) 3008 | register_instruction(GETSTATIC) 3009 | register_instruction(PUTSTATIC) 3010 | register_instruction(GOTO) 3011 | register_instruction(GOTO_W) 3012 | register_instruction(IADD) 3013 | register_instruction(LADD) 3014 | register_instruction(FADD) 3015 | register_instruction(DADD) 3016 | register_instruction(ISUB) 3017 | register_instruction(FSUB) 3018 | register_instruction(LSUB) 3019 | register_instruction(DSUB) 3020 | register_instruction(IMUL) 3021 | register_instruction(LMUL) 3022 | register_instruction(FMUL) 3023 | register_instruction(DMUL) 3024 | register_instruction(IDIV) 3025 | register_instruction(LDIV) 3026 | register_instruction(FDIV) 3027 | register_instruction(DDIV) 3028 | register_instruction(IREM) 3029 | register_instruction(LREM) 3030 | register_instruction(FREM) 3031 | register_instruction(DREM) 3032 | register_instruction(INEG) 3033 | register_instruction(LNEG) 3034 | register_instruction(FNEG) 3035 | register_instruction(DNEG) 3036 | register_instruction(ISHL) 3037 | register_instruction(LSHL) 3038 | register_instruction(ISHR) 3039 | register_instruction(LSHR) 3040 | register_instruction(IUSHR) 3041 | register_instruction(LUSHR) 3042 | register_instruction(IAND) 3043 | register_instruction(LAND) 3044 | register_instruction(IOR) 3045 | register_instruction(LOR) 3046 | register_instruction(IXOR) 3047 | register_instruction(LXOR) 3048 | register_instruction(IINC) 3049 | register_instruction(I2L) 3050 | register_instruction(I2F) 3051 | register_instruction(I2D) 3052 | register_instruction(L2I) 3053 | register_instruction(L2F) 3054 | register_instruction(L2D) 3055 | register_instruction(F2I) 3056 | register_instruction(F2L) 3057 | register_instruction(F2D) 3058 | register_instruction(D2I) 3059 | register_instruction(D2L) 3060 | register_instruction(D2F) 3061 | register_instruction(I2B) 3062 | register_instruction(I2C) 3063 | register_instruction(I2S) 3064 | register_instruction(LCMP) 3065 | register_instruction(FCMPL) 3066 | register_instruction(FCMPD) 3067 | register_instruction(DCMPL) 3068 | register_instruction(DCMPD) 3069 | register_instruction(IFEQ) 3070 | register_instruction(IFNE) 3071 | register_instruction(IFLT) 3072 | register_instruction(IFGE) 3073 | register_instruction(IFGT) 3074 | register_instruction(IFLE) 3075 | register_instruction(ICONST_M1) 3076 | register_instruction(ICONST_0) 3077 | register_instruction(ICONST_1) 3078 | register_instruction(ICONST_2) 3079 | register_instruction(ICONST_3) 3080 | register_instruction(ICONST_4) 3081 | register_instruction(ICONST_5) 3082 | register_instruction(LCONST_0) 3083 | register_instruction(LCONST_1) 3084 | register_instruction(FCONST_0) 3085 | register_instruction(FCONST_1) 3086 | register_instruction(FCONST_2) 3087 | register_instruction(DCONST_0) 3088 | register_instruction(DCONST_1) 3089 | register_instruction(IF_ICMPEQ) 3090 | register_instruction(IF_ICMPGE) 3091 | register_instruction(IF_ICMPGT) 3092 | register_instruction(IF_ICMPLE) 3093 | register_instruction(IF_ICMPLT) 3094 | register_instruction(IF_ICMPNE) 3095 | register_instruction(IF_ACMPEQ) 3096 | register_instruction(IF_ACMPNE) 3097 | register_instruction(DLOAD) 3098 | register_instruction(DLOAD_0) 3099 | register_instruction(DLOAD_1) 3100 | register_instruction(DLOAD_2) 3101 | register_instruction(DLOAD_3) 3102 | register_instruction(FLOAD) 3103 | register_instruction(FLOAD_0) 3104 | register_instruction(FLOAD_1) 3105 | register_instruction(FLOAD_2) 3106 | register_instruction(FLOAD_3) 3107 | register_instruction(ILOAD) 3108 | register_instruction(ILOAD_0) 3109 | register_instruction(ILOAD_1) 3110 | register_instruction(ILOAD_2) 3111 | register_instruction(ILOAD_3) 3112 | register_instruction(LLOAD) 3113 | register_instruction(LLOAD_0) 3114 | register_instruction(LLOAD_1) 3115 | register_instruction(LLOAD_2) 3116 | register_instruction(LLOAD_3) 3117 | register_instruction(DSTORE) 3118 | register_instruction(DSTORE_0) 3119 | register_instruction(DSTORE_1) 3120 | register_instruction(DSTORE_2) 3121 | register_instruction(DSTORE_3) 3122 | register_instruction(FSTORE) 3123 | register_instruction(FSTORE_0) 3124 | register_instruction(FSTORE_1) 3125 | register_instruction(FSTORE_2) 3126 | register_instruction(FSTORE_3) 3127 | register_instruction(IASTORE) 3128 | register_instruction(IALOAD) 3129 | register_instruction(CASTORE) 3130 | register_instruction(CALOAD) 3131 | register_instruction(DASTORE) 3132 | register_instruction(DALOAD) 3133 | register_instruction(FASTORE) 3134 | register_instruction(FALOAD) 3135 | register_instruction(LASTORE) 3136 | register_instruction(LALOAD) 3137 | register_instruction(SASTORE) 3138 | register_instruction(SALOAD) 3139 | register_instruction(AASTORE) 3140 | register_instruction(AALOAD) 3141 | register_instruction(BASTORE) 3142 | register_instruction(BALOAD) 3143 | register_instruction(ISTORE) 3144 | register_instruction(ISTORE_0) 3145 | register_instruction(ISTORE_1) 3146 | register_instruction(ISTORE_2) 3147 | register_instruction(ISTORE_3) 3148 | register_instruction(LSTORE) 3149 | register_instruction(LSTORE_0) 3150 | register_instruction(LSTORE_1) 3151 | register_instruction(LSTORE_2) 3152 | register_instruction(LSTORE_3) 3153 | register_instruction(IMPDEP1) 3154 | register_instruction(IMPDEP2) 3155 | register_instruction(INVOKESPECIAL) 3156 | register_instruction(INVOKESTATIC) 3157 | register_instruction(INVOKEVIRTUAL) 3158 | register_instruction(RETURN) 3159 | register_instruction(IRETURN) 3160 | register_instruction(LRETURN) 3161 | register_instruction(FRETURN) 3162 | register_instruction(DRETURN) 3163 | register_instruction(ARETURN) 3164 | register_instruction(LDC) 3165 | register_instruction(LDC_W) 3166 | register_instruction(LDC2_W) 3167 | register_instruction(NEW) 3168 | register_instruction(NEWARRAY) 3169 | register_instruction(ANEWARRAY) 3170 | register_instruction(ARRAY_LENGTH) 3171 | register_instruction(POP) 3172 | register_instruction(POP2) 3173 | register_instruction(PUTFIELD) 3174 | register_instruction(GETFIELD) 3175 | register_instruction(SIPUSH) 3176 | register_instruction(SWAP) 3177 | register_instruction(TABLE_SWITCH) 3178 | register_instruction(LOOK_UP_SWITCH) 3179 | register_instruction(CHECK_CAST) 3180 | register_instruction(INSTANCE_OF) 3181 | register_instruction(WIDE) 3182 | register_instruction(IF_NULL) 3183 | register_instruction(IF_NON_NULL) 3184 | register_instruction(ATHROW) 3185 | 3186 | 3187 | def get_instruction(code): 3188 | if code in instruction_cache: 3189 | return instruction_cache[code]() 3190 | error_handler.rise_runtime_error('sorry! code %x is not realized!' % code) 3191 | 3192 | 3193 | if __name__ == '__main__': 3194 | print(sorted(instruction_cache)) 3195 | for code in range(255): 3196 | if code not in instruction_cache: 3197 | print('%x' % code) 3198 | -------------------------------------------------------------------------------- /interpreter/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/5A59/Zvm/d093558c567488472252a4f6f87cecbc0ec2bd38/interpreter/__init__.py -------------------------------------------------------------------------------- /interpreter/code_parser.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | 3 | from base.utils import print_utils, error_handler 4 | import ctypes 5 | 6 | 7 | class CodeParser(object): 8 | def __init__(self, code): 9 | self.code = code 10 | self.pc = 0 11 | 12 | def reset(self, code, pc): 13 | self.code = code 14 | self.pc = pc 15 | 16 | def check_pc(self): 17 | if self.pc >= len(self.code): 18 | print_utils.print_error("pc out of index in code parser") 19 | error_handler.rise_runtime_error("pc out of index in code parser") 20 | 21 | def read_code(self): 22 | self.check_pc() 23 | ins = self.code[self.pc] 24 | self.pc += 1 25 | return ins 26 | 27 | # 读操作数 28 | def read_op(self): 29 | self.check_pc() 30 | op = self.code[self.pc] 31 | self.pc += 1 32 | return op 33 | 34 | def jump_by(self, off): 35 | self.pc += off 36 | 37 | # switch 指令使用 使得地址都是 4 的倍数 38 | def skip_padding(self): 39 | while self.pc % 4 != 0: 40 | self.read_op() 41 | 42 | def read_4byte(self): 43 | byte1 = self.read_op() 44 | byte2 = self.read_op() 45 | byte3 = self.read_op() 46 | byte4 = self.read_op() 47 | byte = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4 48 | return ctypes.c_int32(byte).value 49 | -------------------------------------------------------------------------------- /interpreter/interpreter.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | 3 | from runtime.thread import Thread, Frame, JavaStack 4 | from runtime.jclass import Method 5 | from base.utils import print_utils, error_handler 6 | from instruction import instruction 7 | from interpreter.code_parser import CodeParser 8 | from jgc.gc import GC 9 | import threading 10 | 11 | 12 | class Interpreter(object): 13 | def __init__(self): 14 | self.thread = None 15 | 16 | def run(self, method): 17 | print_utils.print_jvm_status(threading.currentThread.__name__) 18 | print_utils.print_jvm_status('\n=================== running status =====================\n') 19 | self.thread = Thread.new_thread() 20 | thread = self.thread 21 | frame = Frame(thread, method) 22 | thread.add_frame(frame) 23 | code_parser = CodeParser(method.code) 24 | while True: 25 | if not thread.has_frame(): 26 | break 27 | GC.check_gc() 28 | frame = thread.top_frame() 29 | method = frame.method 30 | code_parser.reset(method.code, frame.pc) 31 | ins_code = code_parser.read_code() 32 | print_utils.print_jvm_status('ins_code: %x' % ins_code) 33 | ins = instruction.get_instruction(ins_code) 34 | ins.read_operands(code_parser) 35 | thread.pc = frame.pc # 保存上一条 pc 36 | frame.pc = code_parser.pc 37 | ins.execute_wrapper(frame) 38 | 39 | print_utils.print_jvm_status('\n=================== output =====================') 40 | print_utils.StreamPrinter.print_all(thread) 41 | Thread.finish_thread(thread) 42 | 43 | @staticmethod 44 | def exec_method(method): 45 | m_interpreter = Interpreter() 46 | m_interpreter.run(method) 47 | -------------------------------------------------------------------------------- /java_class/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/5A59/Zvm/d093558c567488472252a4f6f87cecbc0ec2bd38/java_class/__init__.py -------------------------------------------------------------------------------- /java_class/class_file.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | 3 | 4 | def get_string_from_attribute_array(attrs): 5 | res = '' 6 | for attr in attrs: 7 | res += '{%s},' % attr 8 | return res 9 | 10 | 11 | class ClassFile(object): 12 | def __init__(self): 13 | self.magic = None # u4 14 | self.minor_version = None # u2 15 | self.major_version = None # u2 16 | self.constant_pool_count = None # u2 17 | self.constant_pool = None # cp_info 18 | self.access_flag = None # u2 19 | self.this_class = None # u2 20 | self.super_class = None # u2 21 | self.interface_count = None # u2 22 | self.interfaces = None # u2 23 | self.fields_count = None # u2 24 | self.fields = None # field_info 25 | self.methods_count = None # u2 26 | self.methods = None # method_info 27 | self.attributes_count = None # u2 28 | self.attributes = None # attribute_info 29 | 30 | 31 | class ConstantPoolBaseInfo(object): 32 | CONSTANT_CLASS = 7 33 | CONSTANT_FIELD_REF = 9 34 | CONSTANT_METHOD_REF = 10 35 | CONSTANT_INTERFACE_METHOD_REF = 11 36 | CONSTANT_STRING = 8 37 | CONSTANT_INTEGER = 3 38 | CONSTANT_FLOAT = 4 39 | CONSTANT_LONG = 5 40 | CONSTANT_DOUBLE = 6 41 | CONSTANT_NAME_AND_TYPE = 12 42 | CONSTANT_UTF_8 = 1 43 | CONSTANT_METHOD_HANDLE = 15 44 | CONSTANT_METHOD_TYPE = 16 45 | CONSTANT_INVOKE_DYNAMIC = 18 46 | 47 | def __init__(self): 48 | self.tag = None # u1 49 | 50 | 51 | # ============= 以下是常量池数据结构 ============== 52 | class ClassInfo(ConstantPoolBaseInfo): 53 | def __init__(self): 54 | super(ClassInfo, self).__init__() 55 | self.tag = ConstantPoolBaseInfo.CONSTANT_CLASS 56 | self.name_index = None # 对常量池的索引 索引项是 CONSTANT_UTF_8 eg. 57 | 58 | def __str__(self): 59 | return 'CONSTANT_CLASS{tag:%s, name_index: %s}' % (self.tag, self.name_index) 60 | 61 | @staticmethod 62 | def get_size(): 63 | return 3 64 | 65 | 66 | class RefInfo(ConstantPoolBaseInfo): 67 | def __init__(self): 68 | super(RefInfo, self).__init__() 69 | self.class_index = None # u2 索引 class_info 70 | self.name_and_type_index = None # u2 索引 name_and_type_info 表示字段或者方法的名字和描述符 71 | 72 | @staticmethod 73 | def get_size(): 74 | return 5 75 | 76 | 77 | class FieldRefInfo(RefInfo): 78 | def __init__(self): 79 | super(FieldRefInfo, self).__init__() 80 | self.tag = ConstantPoolBaseInfo.CONSTANT_FIELD_REF 81 | 82 | def __str__(self): 83 | return 'CONSTANT_FIELD_REF{tag:%s, name_and_type_index: %s}' % (self.tag, self.name_and_type_index) 84 | 85 | 86 | class MethodRefInfo(RefInfo): 87 | def __init__(self): 88 | super(MethodRefInfo, self).__init__() 89 | self.tag = ConstantPoolBaseInfo.CONSTANT_METHOD_REF 90 | 91 | def __str__(self): 92 | return 'CONSTANT_METHOD_REF{tag:%s, name_and_type_index: %s}' % (self.tag, self.name_and_type_index) 93 | 94 | 95 | class InterfaceMethodRefInfo(RefInfo): 96 | def __init__(self): 97 | super(InterfaceMethodRefInfo, self).__init__() 98 | self.tag = ConstantPoolBaseInfo.CONSTANT_INTERFACE_METHOD_REF 99 | 100 | def __str__(self): 101 | return 'CONSTANT_INTERFACE_METHOD_REF{tag:%s, name_and_type_index: %s}' % (self.tag, self.name_and_type_index) 102 | 103 | 104 | class StringInfo(ConstantPoolBaseInfo): 105 | def __init__(self): 106 | super(StringInfo, self).__init__() 107 | self.tag = ConstantPoolBaseInfo.CONSTANT_STRING 108 | self.string_index = None # 索引 utf8_info 表示一组 unicode 码点序列 109 | 110 | def __str__(self): 111 | return 'CONSTANT_STRING{tag:%s, string_index: %s}' % (self.tag, self.string_index) 112 | 113 | @staticmethod 114 | def get_size(): 115 | return 3 116 | 117 | 118 | class U4Info(ConstantPoolBaseInfo): 119 | def __init__(self): 120 | super(U4Info, self).__init__() 121 | self.bytes = None # u4 big-endian 122 | 123 | @staticmethod 124 | def get_size(): 125 | return 5 126 | 127 | 128 | class IntegerInfo(U4Info): 129 | def __init__(self): 130 | super(IntegerInfo, self).__init__() 131 | self.tag = ConstantPoolBaseInfo.CONSTANT_INTEGER 132 | 133 | def __str__(self): 134 | return 'CONSTANT_INTEGER{tag:%s, bytes: %s}' % (self.tag, self.bytes) 135 | 136 | 137 | class FloatInfo(U4Info): 138 | def __init__(self): 139 | super(FloatInfo, self).__init__() 140 | self.tag = ConstantPoolBaseInfo.CONSTANT_FLOAT 141 | 142 | def __str__(self): 143 | return 'CONSTANT_FLOAT{tag:%s, bytes: %s}' % (self.tag, self.bytes) 144 | 145 | 146 | class U8Info(ConstantPoolBaseInfo): 147 | def __init__(self): 148 | super(U8Info, self).__init__() 149 | self.high_bytes = None # u4 150 | self.low_bytes = None # u4 151 | 152 | @staticmethod 153 | def get_size(): 154 | return 9 155 | 156 | 157 | class LongInfo(U8Info): 158 | def __init__(self): 159 | super(LongInfo, self).__init__() 160 | self.tag = ConstantPoolBaseInfo.CONSTANT_LONG 161 | 162 | def __str__(self): 163 | return 'CONSTANT_LONG{tag:%s, high_bytes: %s, low_bytes: %s}' % (self.tag, self.high_bytes, self.low_bytes) 164 | 165 | 166 | class DoubleInfo(U8Info): 167 | def __init__(self): 168 | super(DoubleInfo, self).__init__() 169 | self.tag = ConstantPoolBaseInfo.CONSTANT_DOUBLE 170 | 171 | def __str__(self): 172 | return 'CONSTANT_DOUBLE{tag:%s, high_bytes: %s, low_bytes: %s}' % (self.tag, self.high_bytes, self.low_bytes) 173 | 174 | 175 | class NameAndTypeInfo(ConstantPoolBaseInfo): 176 | def __init__(self): 177 | super(NameAndTypeInfo, self).__init__() 178 | self.tag = ConstantPoolBaseInfo.CONSTANT_NAME_AND_TYPE 179 | self.name_index = None # u2 索引 名字 180 | self.descriptor_index = None # u2 索引 描述符 181 | 182 | def __str__(self): 183 | return 'CONSTANT_NAME_AND_TYPE{tag:%s, name_index: %s, descriptor_index: %s}' \ 184 | % (self.tag, self.name_index, self.descriptor_index) 185 | 186 | @staticmethod 187 | def get_size(): 188 | return 5 189 | 190 | 191 | class Utf8Info(ConstantPoolBaseInfo): 192 | def __init__(self): 193 | super(Utf8Info, self).__init__() 194 | self.tag = ConstantPoolBaseInfo.CONSTANT_UTF_8 195 | self.length = None # u2 196 | self.bytes = None # bytes[length] 197 | 198 | def __str__(self): 199 | return 'CONSTANT_UTF_8{tag:%s, length: %s, bytes: %s}' % (self.tag, self.length, self.bytes) 200 | 201 | def get_size(self): 202 | return self.length + 3 203 | 204 | 205 | class MethodHandleInfo(ConstantPoolBaseInfo): 206 | def __init__(self): 207 | super(MethodHandleInfo, self).__init__() 208 | self.tag = ConstantPoolBaseInfo.CONSTANT_METHOD_HANDLE 209 | self.reference_kind = None # u1 方法句柄类型 210 | self.reference_index = None # u2 索引 211 | 212 | def __str__(self): 213 | return 'CONSTANT_UTF_8{tag:%s, reference_kind: %s, : reference_index%s}' \ 214 | % (self.tag, self.reference_kind, self.reference_index) 215 | 216 | @staticmethod 217 | def get_size(): 218 | return 4 219 | 220 | 221 | class MethodTypeInfo(ConstantPoolBaseInfo): 222 | def __init__(self): 223 | super(MethodTypeInfo, self).__init__() 224 | self.tag = ConstantPoolBaseInfo.CONSTANT_METHOD_TYPE 225 | self.descriptor_index = None # 索引 方法描述符 226 | 227 | def __str__(self): 228 | return 'CONSTANT_METHOD_TYPE{tag:%s, descriptor_index: %s' % (self.tag, self.descriptor_index) 229 | 230 | @staticmethod 231 | def get_size(): 232 | return 3 233 | 234 | 235 | class InvokeDynamicInfo(ConstantPoolBaseInfo): 236 | def __init__(self): 237 | super(InvokeDynamicInfo, self).__init__() 238 | self.tag = ConstantPoolBaseInfo.CONSTANT_INVOKE_DYNAMIC 239 | self.bootstrap_method_attr_index = None # u2 引导方法表索引 240 | self.name_and_type_index = None # u2 索引 241 | 242 | def __str__(self): 243 | return 'CONSTANT_INVOKE_DYNAMIC{tag:%s, bootstrap_method_attr_index: %s, name_and_type_index: %s' \ 244 | % (self.tag, self.bootstrap_method_attr_index, self.name_and_type_index) 245 | 246 | @staticmethod 247 | def get_size(): 248 | return 5 249 | 250 | # ============= 以上是常量池数据结构 ============== 251 | 252 | 253 | class FieldInfo(object): 254 | def __init__(self): 255 | self.access_flags = None # u2 256 | self.name_index = None # u2 257 | self.descriptor_index = None # u2 258 | self.attributes_count = None # u2 259 | self.attributes = None # attribute_info 260 | 261 | def __str__(self): 262 | return 'Field{access_flags: %s, name_index: %s, descriptor_index: %s, attributes_count: %s, attributes: %s}' \ 263 | % (self.access_flags, self.name_index, self.descriptor_index, self.attributes_count, 264 | get_string_from_attribute_array(self.attributes)) 265 | 266 | 267 | class MethodInfo(object): 268 | def __init__(self): 269 | self.access_flags = None # u2 270 | self.name_index = None # u2 常量池索引 utf8_info 271 | self.descriptor_index = None # u2 常量池索引 utf8_info 272 | self.attributes_count = None # u2 273 | self.attributes = None # attribute_info 274 | 275 | def __str__(self): 276 | return 'METHOD_INFO{access_flag: %s, name_index: %s, descriptor_index: %s, ' \ 277 | 'attributes_count: %s, attributes: %s}' \ 278 | % (self.access_flags, self.name_index, self.descriptor_index, self.attributes_count, 279 | get_string_from_attribute_array(self.attributes)) 280 | 281 | 282 | class BaseAttribute(object): 283 | ATTR_CONSTANT_VALUE = 'ConstantValue' 284 | ATTR_CODE = 'Code' 285 | ATTR_SOURCE_FILE = 'SourceFile' 286 | ATTR_SIGNATURE = 'Signature' 287 | ATTR_EXCEPTIONS = 'Exceptions' 288 | 289 | def __init__(self): 290 | self.attribute_name_index = None # u2 对常量池的索引 utf8_info 291 | self.attribute_length = None # u4 292 | 293 | 294 | class ConstantValueAttribute(BaseAttribute): 295 | def __init__(self): 296 | super(ConstantValueAttribute, self).__init__() 297 | self.attribute_length = 2 298 | self.constant_value_index = None # u2 对常量池的索引 299 | 300 | def __str__(self): 301 | return 'CONSTANT_VALUE_ATTR{attribute_name_index: %s, attribute_length: %s, constant_value_index: %s' \ 302 | % (self.attribute_name_index, self.attribute_length, self.constant_value_index) 303 | 304 | 305 | class ExceptionTable(object): 306 | def __init__(self): 307 | self.start_pc = None # u2 308 | self.end_pc = None # u2 异常处理器在 code[] 中的有效范围 end_pc 本身不属于异常处理器范围 309 | self.handler_pc = None # u2 异常处理器的起点 310 | self.catch_type = None # u2 对常量池的索引,CONSTANT_CLASS_INFO 指定异常的类型 311 | 312 | 313 | class CodeAttribute(BaseAttribute): 314 | def __init__(self): 315 | super(CodeAttribute, self).__init__() 316 | self.max_stack = None # u2 317 | self.max_locals = None # u2 318 | self.code_length = None # u4 319 | self.code = None # u1 长度 code_length 320 | self.exception_table_length = None # u2 321 | self.exception_table = None # exception_table_length ExceptionTable 322 | self.attributes_count = None # u2 323 | self.attributes = None 324 | 325 | def __str__(self): 326 | return 'CODE_ATTR{max_stack: %s, max_locals: %s, code_length: %s, ' \ 327 | 'code: %s, exception_table_length: %s, exception_table: %s, ' \ 328 | 'attributes_count: %s, attributes: %s}' \ 329 | % (self.max_locals, self.max_locals, self.code_length, self.code, 330 | self.exception_table_length, self.exception_table, self.attributes_count, 331 | get_string_from_attribute_array(self.attributes)) 332 | 333 | 334 | class SourceFileAttribute(BaseAttribute): 335 | def __init__(self): 336 | super(SourceFileAttribute, self).__init__() 337 | self.sourcefile_index = None # u2 常量池索引,utf8_info class 文件源文件名字,不包括目录 338 | 339 | def __str__(self): 340 | return 'SOURCE_FILE_ATTR{sourcefile_index: %s}' % self.sourcefile_index 341 | 342 | 343 | class SignatureAttribute(BaseAttribute): 344 | def __init__(self): 345 | super(SignatureAttribute, self).__init__() 346 | self.signature_index = None 347 | 348 | def __str__(self): 349 | return 'SIGNATURE_ATTR{signature_index: %s}' % self.signature_index 350 | 351 | 352 | class ExceptionsAttribute(BaseAttribute): 353 | def __init__(self): 354 | super(ExceptionsAttribute, self).__init__() 355 | self.number_of_exceptions = 0 # u2 356 | self.exception_index_table = None # index 数组,长度 number_of_exceptions 357 | -------------------------------------------------------------------------------- /java_class/class_parser.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | 3 | from java_class.class_file import * 4 | from base.utils import common_utils 5 | 6 | 7 | class ClassReader: 8 | def __init__(self, path): 9 | self.path = path 10 | with open(self.path, 'rb') as f: 11 | self.array = bytearray(f.read()) 12 | self.index = 0 13 | 14 | def read_b1(self): 15 | res = self.array[self.index] 16 | self.index += 1 17 | return res 18 | 19 | def read_b2(self): 20 | res = self.array[self.index: self.index + 2] 21 | self.index += 2 22 | return res 23 | 24 | def read_b4(self): 25 | res = self.array[self.index: self.index + 4] 26 | self.index += 4 27 | return res 28 | 29 | def read_bn(self, length): 30 | res = self.array[self.index: self.index + length] 31 | self.index += length 32 | return res 33 | 34 | 35 | # TODO: class 格式校验 36 | class ClassParser: 37 | def __init__(self, path): 38 | self.reader = ClassReader(path) 39 | self.class_file = ClassFile() 40 | 41 | def read_magic(self): 42 | self.class_file.magic = self.reader.read_b4() 43 | 44 | def read_minor_version(self): 45 | self.class_file.minor_version = self.reader.read_b2() 46 | 47 | def read_major_version(self): 48 | self.class_file.major_version = self.reader.read_b2() 49 | 50 | def read_constant_pool_count(self): 51 | self.class_file.constant_pool_count = self.reader.read_b2() 52 | 53 | def read_constant_pool(self): 54 | constant_pool = [None] # constant_pool 第 0 个元素无用 55 | skip = False 56 | for i in range(common_utils.get_int_from_bytes(self.class_file.constant_pool_count) - 1): 57 | if skip: # long double 占两个槽 58 | constant_pool.append(None) 59 | skip = False 60 | continue 61 | info = None 62 | tag = self.reader.read_b1() 63 | if tag == ConstantPoolBaseInfo.CONSTANT_CLASS: 64 | info = ClassInfo() 65 | info.tag = tag 66 | info.name_index = self.reader.read_b2() 67 | elif tag == ConstantPoolBaseInfo.CONSTANT_FIELD_REF: 68 | info = FieldRefInfo() 69 | info.tag = tag 70 | info.class_index = self.reader.read_b2() 71 | info.name_and_type_index = self.reader.read_b2() 72 | elif tag == ConstantPoolBaseInfo.CONSTANT_METHOD_REF: 73 | info = MethodRefInfo() 74 | info.tag = tag 75 | info.class_index = self.reader.read_b2() 76 | info.name_and_type_index = self.reader.read_b2() 77 | elif tag == ConstantPoolBaseInfo.CONSTANT_INTERFACE_METHOD_REF: 78 | info = InterfaceMethodRefInfo() 79 | info.tag = tag 80 | info.class_index = self.reader.read_b2() 81 | info.name_and_type_index = self.reader.read_b2() 82 | elif tag == ConstantPoolBaseInfo.CONSTANT_STRING: 83 | info = StringInfo() 84 | info.tag = tag 85 | info.string_index = self.reader.read_b2() 86 | elif tag == ConstantPoolBaseInfo.CONSTANT_INTEGER: 87 | info = IntegerInfo() 88 | info.tag = tag 89 | info.bytes = self.reader.read_b4() 90 | elif tag == ConstantPoolBaseInfo.CONSTANT_FLOAT: 91 | info = FloatInfo() 92 | info.tag = tag 93 | info.bytes = self.reader.read_b4() 94 | elif tag == ConstantPoolBaseInfo.CONSTANT_LONG: 95 | info = LongInfo() 96 | info.tag = tag 97 | info.high_bytes = self.reader.read_b4() 98 | info.low_bytes = self.reader.read_b4() 99 | skip = True 100 | elif tag == ConstantPoolBaseInfo.CONSTANT_DOUBLE: 101 | info = DoubleInfo() 102 | info.tag = tag 103 | info.high_bytes = self.reader.read_b4() 104 | info.low_bytes = self.reader.read_b4() 105 | skip = True 106 | elif tag == ConstantPoolBaseInfo.CONSTANT_NAME_AND_TYPE: 107 | info = NameAndTypeInfo() 108 | info.tag = tag 109 | info.name_index = self.reader.read_b2() 110 | info.descriptor_index = self.reader.read_b2() 111 | elif tag == ConstantPoolBaseInfo.CONSTANT_UTF_8: 112 | info = Utf8Info() 113 | info.tag = tag 114 | info.length = self.reader.read_b2() 115 | info.bytes = self.reader.read_bn(common_utils.get_int_from_bytes(info.length)) 116 | elif tag == ConstantPoolBaseInfo.CONSTANT_METHOD_HANDLE: 117 | info = MethodHandleInfo() 118 | info.tag = tag 119 | info.reference_kind = self.reader.read_b1() 120 | info.reference_index = self.reader.read_b2() 121 | elif tag == ConstantPoolBaseInfo.CONSTANT_METHOD_TYPE: 122 | info = MethodTypeInfo() 123 | info.tag = tag 124 | info.descriptor_index = self.reader.read_b2() 125 | elif tag == ConstantPoolBaseInfo.CONSTANT_INVOKE_DYNAMIC: 126 | info = InvokeDynamicInfo() 127 | info.tag = tag 128 | info.bootstrap_method_attr_index = self.reader.read_b2() 129 | info.name_and_type_index = self.reader.read_b2() 130 | 131 | if info is not None: 132 | constant_pool.append(info) 133 | self.class_file.constant_pool = constant_pool 134 | 135 | def read_access_flags(self): 136 | self.class_file.access_flag = self.reader.read_b2() 137 | 138 | def read_this_class(self): 139 | self.class_file.this_class = self.reader.read_b2() 140 | 141 | def read_super_class(self): 142 | self.class_file.super_class = self.reader.read_b2() 143 | 144 | def read_interfaces_count(self): 145 | self.class_file.interface_count = self.reader.read_b2() 146 | 147 | def read_interfaces(self): 148 | tmp_class_file = self.class_file 149 | interfaces = [] 150 | for i in range(common_utils.get_int_from_bytes(tmp_class_file.interface_count)): 151 | interfaces.append(self.reader.read_b2()) 152 | tmp_class_file.interfaces = interfaces 153 | 154 | def read_fields_count(self): 155 | self.class_file.fields_count = self.reader.read_b2() 156 | 157 | def read_fields(self): 158 | tmp_class_file = self.class_file 159 | fields = [] 160 | for i in range(common_utils.get_int_from_bytes(tmp_class_file.fields_count)): 161 | field = FieldInfo() 162 | field.access_flags = self.reader.read_b2() 163 | field.name_index = self.reader.read_b2() 164 | field.descriptor_index = self.reader.read_b2() 165 | field.attributes_count = self.reader.read_b2() 166 | field.attributes = self.read_attributes_(common_utils.get_int_from_bytes(field.attributes_count)) 167 | fields.append(field) 168 | tmp_class_file.fields = fields 169 | 170 | def read_methods_count(self): 171 | self.class_file.methods_count = self.reader.read_b2() 172 | 173 | def read_methods(self): 174 | tmp_class = self.class_file 175 | methods = [] 176 | for i in range(common_utils.get_int_from_bytes(self.class_file.methods_count)): 177 | method = MethodInfo() 178 | method.access_flags = self.reader.read_b2() 179 | method.name_index = self.reader.read_b2() 180 | method.descriptor_index = self.reader.read_b2() 181 | method.attributes_count = self.reader.read_b2() 182 | method.attributes = self.read_attributes_(common_utils.get_int_from_bytes(method.attributes_count)) 183 | methods.append(method) 184 | tmp_class.methods = methods 185 | 186 | def read_attributes_count(self): 187 | self.class_file.attributes_count = self.reader.read_b2() 188 | 189 | def read_attributes(self): 190 | self.class_file.attributes = self.read_attributes_( 191 | common_utils.get_int_from_bytes(self.class_file.attributes_count)) 192 | 193 | def read_attributes_(self, attributes_count): 194 | tmp_class = self.class_file 195 | attributes = [] 196 | for i in range(attributes_count): 197 | attribute_name_index = self.reader.read_b2() 198 | attribute_length = self.reader.read_b4() 199 | attr_name = tmp_class.constant_pool[common_utils.get_int_from_bytes(attribute_name_index)] 200 | attr_name = common_utils.get_string_from_bytes(attr_name.bytes) 201 | # TODO: 重构一下这个地方,有点乱看着 202 | if attr_name == BaseAttribute.ATTR_CONSTANT_VALUE: 203 | attr = ConstantValueAttribute() 204 | attr.attribute_name_index = attribute_name_index 205 | attr.attribute_length = attribute_length 206 | attr.constant_value_index = self.reader.read_b2() 207 | attributes.append(attr) 208 | elif attr_name == BaseAttribute.ATTR_CODE: 209 | attr = CodeAttribute() 210 | attr.attribute_name_index = attribute_name_index 211 | attr.attribute_length = attribute_length 212 | attr.max_stack = self.reader.read_b2() 213 | attr.max_locals = self.reader.read_b2() 214 | attr.code_length = self.reader.read_b4() 215 | attr.code = self.reader.read_bn(common_utils.get_int_from_bytes(attr.code_length)) 216 | attr.exception_table_length = self.reader.read_b2() 217 | attr.exception_table = self.read_exception_table( 218 | common_utils.get_int_from_bytes(attr.exception_table_length)) 219 | attr.attributes_count = self.reader.read_b2() 220 | attr.attributes = self.read_attributes_(common_utils.get_int_from_bytes(attr.attributes_count)) 221 | attributes.append(attr) 222 | elif attr_name == BaseAttribute.ATTR_SOURCE_FILE: 223 | attr = SourceFileAttribute() 224 | attr.attribute_name_index = attribute_name_index 225 | attr.attribute_length = attribute_length 226 | attr.sourcefile_index = self.reader.read_b2() 227 | attributes.append(attr) 228 | elif attr_name == BaseAttribute.ATTR_SIGNATURE: 229 | attr = SignatureAttribute() 230 | attr.attribute_name_index = attribute_name_index 231 | attr.attribute_length = attribute_length 232 | attr.signature_index = self.reader.read_b2() 233 | attributes.append(attr) 234 | # TODO: 这个 Exception 和 code 里的 exception 有什么区别? 235 | elif attr_name == BaseAttribute.ATTR_EXCEPTIONS: 236 | # attr = ExceptionsAttribute() 237 | # attr.attribute_name_index = attribute_name_index 238 | # attr.attribute_length = attribute_length 239 | # attr.number_of_exceptions = self.reader.read_b2() 240 | # attributes.append(attr) 241 | self.reader.read_bn(common_utils.get_int_from_bytes(attribute_length)) 242 | attributes.append(None) 243 | else: # 不认识的属性跳过 244 | self.reader.read_bn(common_utils.get_int_from_bytes(attribute_length)) 245 | attributes.append(None) 246 | return attributes 247 | 248 | def read_exception_table(self, length): 249 | exceptions = [] 250 | for i in range(length): 251 | ex = ExceptionTable() 252 | ex.start_pc = self.reader.read_b2() 253 | ex.end_pc = self.reader.read_b2() 254 | ex.handler_pc = self.reader.read_b2() 255 | ex.catch_type = self.reader.read_b2() 256 | exceptions.append(ex) 257 | return exceptions 258 | 259 | def parse(self): 260 | self.read_magic() 261 | self.read_minor_version() 262 | self.read_major_version() 263 | self.read_constant_pool_count() 264 | self.read_constant_pool() 265 | self.read_access_flags() 266 | self.read_this_class() 267 | self.read_super_class() 268 | self.read_interfaces_count() 269 | self.read_interfaces() 270 | self.read_fields_count() 271 | self.read_fields() 272 | self.read_methods_count() 273 | self.read_methods() 274 | self.read_attributes_count() 275 | self.read_attributes() 276 | 277 | def __str__(self): 278 | tmp_class = self.class_file 279 | return "magic: %s, minor_version: %s" % (tmp_class.magic, tmp_class.minor_version) 280 | 281 | 282 | if __name__ == '__main__': 283 | parser = ClassParser('../test/Hello.class') 284 | parser.parse() 285 | clf = parser.class_file 286 | print('========= magic =========') 287 | print(parser.class_file.magic) 288 | print('========= minor =========') 289 | print(common_utils.get_int_from_bytes(clf.minor_version)) 290 | print('========= major =========') 291 | print(common_utils.get_int_from_bytes(clf.major_version)) 292 | print('========= constant_pool =========') 293 | constant_pool_count = clf.constant_pool_count 294 | pools = clf.constant_pool 295 | for i in range(common_utils.get_int_from_bytes(constant_pool_count) - 1): 296 | pool = pools[i] 297 | print(pool) 298 | print('========= class =========') 299 | print(common_utils.get_int_from_bytes(clf.access_flag)) 300 | print(clf.this_class) 301 | print(clf.super_class) 302 | print('========= interface =========') 303 | print(clf.interface_count) 304 | for i in range(common_utils.get_int_from_bytes(clf.interface_count)): 305 | print(clf.interfaces[i]) 306 | print('========= fields =========') 307 | print(common_utils.get_int_from_bytes(clf.fields_count)) 308 | for i in range(common_utils.get_int_from_bytes(clf.fields_count)): 309 | print(clf.fields[i]) 310 | print('========= methods =========') 311 | print(common_utils.get_int_from_bytes(clf.methods_count)) 312 | for i in range(common_utils.get_int_from_bytes(clf.methods_count)): 313 | print(clf.methods[i]) 314 | print('========= attributes =========') 315 | print(common_utils.get_int_from_bytes(clf.attributes_count)) 316 | for i in range(common_utils.get_int_from_bytes(clf.attributes_count)): 317 | print(clf.attributes[i]) 318 | 319 | -------------------------------------------------------------------------------- /jgc/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/5A59/Zvm/d093558c567488472252a4f6f87cecbc0ec2bd38/jgc/__init__.py -------------------------------------------------------------------------------- /jgc/gc.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | 3 | from base.utils import print_utils 4 | from runtime.thread import Thread 5 | import runtime 6 | 7 | import threading 8 | 9 | 10 | class GC(object): 11 | __gc_lock = threading.RLock() 12 | 13 | @staticmethod 14 | def check_gc(): # gc 的时候要暂停所有线程 15 | GC.__gc_lock.acquire() 16 | GC.__gc_lock.release() 17 | 18 | @staticmethod 19 | def start_gc(heap, static_fields): 20 | print_utils.print_jvm_status("!!!!!! start gc !!!!!!") 21 | GC.__gc_lock.acquire() 22 | return GCHandler.start_gc(heap, static_fields) 23 | 24 | @staticmethod 25 | def stop_gc(): 26 | GC.__gc_lock.release() 27 | 28 | 29 | class GCHandler(object): 30 | 31 | @staticmethod 32 | def start_gc(heap, static_fields): 33 | alive_obj = GCHandler.collect_alive_ref(static_fields) 34 | alive_list = [] 35 | index = 0 36 | for ref in heap: 37 | if ref in alive_obj: 38 | alive_list.append(index) 39 | index += 1 40 | for i in range(len(heap)): 41 | if i not in alive_list: 42 | heap[i].handler = None 43 | for i in range(len(alive_list)): 44 | heap[i] = heap[alive_list[i]] 45 | return len(alive_list) 46 | 47 | @staticmethod 48 | def collect_alive_ref(static_fields): 49 | # TODO: gc root 目前只收集了 heap 中的对象 和 static 50 | roots = GCHandler.collect_root() 51 | roots.extend(static_fields) 52 | alive_obj = [] 53 | for root in roots: 54 | obj = root.handler.obj 55 | alive_obj.append(root) 56 | if obj.type == runtime.jobject.JObject.TYPE_OBJ: 57 | GCHandler.collect_obj_ref(root, alive_obj) 58 | elif obj.type == runtime.jobject.JObject.TYPE_ARRAY: 59 | GCHandler.collect_array_ref(root, alive_obj) 60 | return alive_obj 61 | 62 | @staticmethod 63 | def collect_obj_ref(ref, alive_obj): 64 | obj = ref.handler.obj 65 | for o in obj.data.values(): 66 | if isinstance(o, runtime.jobject.JRef): 67 | alive_obj.append(o) 68 | GCHandler.collect_obj_ref(o, alive_obj) 69 | 70 | @staticmethod 71 | def collect_array_ref(ref, alive_obj): 72 | array = ref.handler.obj 73 | if array.atype == runtime.jobject.JArray.T_REF: 74 | for slot in array.data: 75 | aref = slot.ref 76 | if aref is not None: 77 | GCHandler.collect_obj_ref(aref, alive_obj) 78 | 79 | @staticmethod 80 | def collect_root(): 81 | thread_pool = Thread.all_thread() 82 | gc_root = [] 83 | for thread in thread_pool: 84 | frames = thread.all_frames() 85 | for frame in frames: 86 | items = frame.operand_stack.get_all_data() 87 | for item in items: 88 | if isinstance(item.data, runtime.jobject.JRef): 89 | gc_root.append(item.data) 90 | vars = frame.local_vars.get_items() 91 | for var in vars: 92 | if isinstance(var.ref, runtime.jobject.JRef): 93 | gc_root.append(var.ref) 94 | return gc_root 95 | 96 | 97 | -------------------------------------------------------------------------------- /jthread/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/5A59/Zvm/d093558c567488472252a4f6f87cecbc0ec2bd38/jthread/__init__.py -------------------------------------------------------------------------------- /jthread/jthread.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | 3 | 4 | from runtime.jclass import Method 5 | import threading 6 | 7 | 8 | class JThread(object): 9 | @staticmethod 10 | def start_new_thread(method): 11 | t = NativeThread(method) 12 | t.start() 13 | 14 | 15 | class NativeThread(threading.Thread): 16 | def __init__(self, method): 17 | super(NativeThread, self).__init__() 18 | self.method = method 19 | 20 | def run(self): 21 | from interpreter.interpreter import Interpreter 22 | Interpreter.exec_method(self.method) 23 | 24 | 25 | class GCThread(object): 26 | pass 27 | -------------------------------------------------------------------------------- /note.md: -------------------------------------------------------------------------------- 1 | 2 | ### 解析 class 文件 3 | 4 | ### 运行时数据区 5 | #### Thread 私有 6 | * PC 7 | * Java 虚拟机栈 8 | * 栈帧 Frame 9 | * 局部变量表 10 | * 操作数栈 11 | * 动态链接: 指向运行时常量池 12 | * 方法返回 13 | 14 | Thread { 15 | Pc 16 | Frame { 17 | LocalVars 18 | OperandStack 19 | DynamicLinking 20 | Method 21 | } 22 | } 23 | 24 | #### 线程共有 25 | * Java 堆: 类实例和数组分配内存的地方, GC 的主要区域 26 | * 方法区: 存储类结构信息, 包括运行时常量池,字段,方法,构造函数和方法的字节码,, 27 | * 运行时常量池: 字面常量等等 28 | * 本地方法栈: native 方法栈 暂不实现 29 | 30 | JavaHeap 31 | MethodArea { 32 | List 33 | } 34 | 35 | ### 指令集和解释器 36 | invokestatic:调用静态方法; 37 | invokespecial:调用实例构造方法,私有方法和父类方法; 38 | invokevirtual:调用虚方法; 39 | invokeinterface:调用接口方法,在运行时再确定一个实现此接口的对象; 40 | invokedynamic:在运行时动态解析出调用点限定符所引用的方法之后,调用该方法; 41 | ### 类和对象 42 | ### 方法调用 43 | ### 数组 44 | ### 本地方法调用(*) 45 | ### 反射 46 | ### 异常 47 | ### 线程 48 | ### gc 49 | 50 | ### 整体架构 / 执行流程 51 | * start: 命令行工具 52 | * parse .class file: 解析 class 文件,保存成类信息 53 | * init: 初始化数据区域,类信息等 54 | * find main method 55 | * run main method: 指令解释器,函数调用,线程,gc,异常,反射 56 | * finish 57 | 58 | 59 | ### Java 虚拟机动态地加载、链接与初始化类和接口。 60 | 加载是根据特定名称查找类或接口类型的 二进制表示(Binary Representation),并由此二进制表示创建类或接口的过程。 61 | 链接是为 了让类或接口可以被 Java 虚拟机执行,而将类或接口并入虚拟机运行时状态的过程。 62 | 类或接口的 初始化是指执行类或接口的初始化方法。 63 | 64 | Java 虚拟机为每个类型都维护一个常量池 65 | 当类或接口创建时(§5.3),它的二进制表示中的 constant_pool 表(§4.4)被用来构 造运行时常量池。 66 | 67 | 68 | ### TODO 69 | 命令行工具 70 | 71 | **先不做的** 72 | vtable 73 | native 方法 74 | 多维数组 75 | -------------------------------------------------------------------------------- /path_import.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | 3 | import sys 4 | import os 5 | sys.path.append([os.getcwd()]) 6 | -------------------------------------------------------------------------------- /res/pic1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/5A59/Zvm/d093558c567488472252a4f6f87cecbc0ec2bd38/res/pic1.png -------------------------------------------------------------------------------- /res/pic2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/5A59/Zvm/d093558c567488472252a4f6f87cecbc0ec2bd38/res/pic2.png -------------------------------------------------------------------------------- /runtime/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/5A59/Zvm/d093558c567488472252a4f6f87cecbc0ec2bd38/runtime/__init__.py -------------------------------------------------------------------------------- /runtime/heap.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | 3 | 4 | from base.utils import error_handler 5 | from jgc.gc import GC 6 | from base.jvm_config import heap_size 7 | 8 | DEF_LENGTH = heap_size 9 | 10 | 11 | class Heap(object): 12 | _java_heap = [None for i in range(DEF_LENGTH)] 13 | _index = 0 # 指向当前可用的位置 14 | _length = DEF_LENGTH 15 | _jclass_heap = [] 16 | 17 | @staticmethod 18 | def new_jclass(jclass): 19 | Heap._jclass_heap.append(jclass) 20 | 21 | @staticmethod 22 | def new_ref(ref): 23 | Heap.__new_ref(ref, True) 24 | 25 | @staticmethod 26 | def __new_ref(ref, retry): 27 | if Heap._index >= Heap._length: 28 | if retry: 29 | Heap.gc() 30 | Heap.__new_ref(ref, False) 31 | else: 32 | error_handler.rise_runtime_error('no heap space !!!') 33 | else: 34 | Heap._java_heap[Heap._index] = ref 35 | Heap._index += 1 36 | 37 | @staticmethod 38 | def collect_static_field(): 39 | static_fields = [] 40 | for jclass in Heap._jclass_heap: 41 | fields = jclass.static_fields 42 | for slot in fields.values(): 43 | if slot.ref is not None: 44 | static_fields.append(slot.ref) 45 | return static_fields 46 | 47 | @staticmethod 48 | def gc(): 49 | Heap._index = GC.start_gc(Heap._java_heap, Heap.collect_static_field()) 50 | GC.stop_gc() 51 | 52 | 53 | if __name__ == '__main__': 54 | Heap.gc() 55 | 56 | -------------------------------------------------------------------------------- /runtime/java_heap.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | 3 | 4 | class JavaHeap: 5 | def __init__(self): 6 | pass 7 | -------------------------------------------------------------------------------- /runtime/jclass.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | 3 | from base.utils import common_utils, print_utils 4 | from java_class.class_file import * 5 | from java_class.class_parser import ClassParser 6 | from runtime.thread import Slot 7 | from runtime.heap import Heap 8 | from base.jvm_config import jdk_path 9 | 10 | import os 11 | 12 | 13 | # 对应 java 中的 Class 14 | class JClass(object): 15 | ACC_PUBLIC = 0x0001 16 | ACC_PRIVATE = 0x0002 17 | ACC_PROTECTED = 0x0004 18 | ACC_STATIC = 0x0008 19 | ACC_FINAL = 0x0010 20 | ACC_VOLATILE = 0x0040 21 | ACC_TRANSIENT = 0x0080 22 | ACC_SYNTHETIC = 0x1000 23 | ACC_ENUM = 0x4000 24 | 25 | @staticmethod 26 | def is_public(flag): 27 | return flag & JClass.ACC_PUBLIC != 0 28 | 29 | @staticmethod 30 | def is_private(flag): 31 | return flag & JClass.ACC_PRIVATE != 0 32 | 33 | @staticmethod 34 | def is_static(flag): 35 | return flag & JClass.ACC_STATIC != 0 36 | 37 | def __init__(self): 38 | self.access_flag = None 39 | self.name = None 40 | self.super_class_name = None 41 | self.super_class = None 42 | self.interfaces = None 43 | self.fields = None 44 | self.methods = None 45 | self.constant_pool = None 46 | self.class_loader = None 47 | self.static_fields = None # map{ name: Slot } 48 | self.has_inited = False 49 | 50 | def new_jclass(self, class_file): 51 | Heap.new_jclass(self) 52 | self.access_flag = common_utils.get_int_from_bytes(class_file.access_flag) 53 | self.constant_pool = ConstantPool.new_constant_pool(class_file) 54 | self.fields = Field.new_fields(class_file.fields, self.constant_pool.constants) 55 | self.methods = Method.new_methods(self, class_file.methods, self.constant_pool.constants) 56 | super_class = self.constant_pool.constants[common_utils.get_int_from_bytes(class_file.super_class)] 57 | if super_class is not None: 58 | self.super_class_name = super_class.class_name # 从方法区取 59 | self.interfaces = None 60 | self.static_fields = {} 61 | for sf in self.__get_static_fields(): 62 | desc = sf.descriptor 63 | slot = Slot() 64 | if desc == 'B' or desc == 'I' or desc == 'J' or desc == 'S' or desc == 'Z': 65 | slot.num = 0 66 | elif desc == 'C': 67 | slot.num = '0' 68 | elif desc == 'F': 69 | slot.num = 0.0 70 | elif desc == 'D': 71 | slot.num = 0.0 72 | self.static_fields[sf.name] = slot 73 | 74 | def get_instance_fields(self): 75 | return [field for field in self.fields if not JClass.is_static(field.access_flag)] 76 | 77 | # return Field[] 78 | def __get_static_fields(self): 79 | return [field for field in self.fields if JClass.is_static(field.access_flag)] 80 | 81 | def get_main_method(self): 82 | methods = self.methods 83 | for method in methods: 84 | if method.name == 'main' and method.descriptor == '([Ljava/lang/String;)V': 85 | return method 86 | return None 87 | 88 | 89 | class ConstantPool(object): 90 | def __init__(self): 91 | self.constants = None 92 | 93 | @staticmethod 94 | def new_constant_pool(class_file): 95 | r_cp = class_file.constant_pool 96 | constants = [] 97 | for cp in r_cp: 98 | if isinstance(cp, ClassInfo): 99 | constants.append(ClassRef.new_class_ref(r_cp, cp)) 100 | elif isinstance(cp, FieldRefInfo): 101 | constants.append(FieldRef.new_field_ref(r_cp, cp)) 102 | elif isinstance(cp, MethodRefInfo): 103 | constants.append(MethodRef.new_method_ref(r_cp, cp)) 104 | elif isinstance(cp, InterfaceMethodRefInfo): 105 | constants.append(None) 106 | elif isinstance(cp, StringInfo): 107 | st = r_cp[common_utils.get_int_from_bytes(cp.string_index)] 108 | st = common_utils.get_string_from_bytes(st.bytes) 109 | jstring = JString() 110 | jstring.data = st 111 | constants.append(jstring) 112 | elif isinstance(cp, IntegerInfo): 113 | jint = JInteger() 114 | jint.data = common_utils.get_int_from_bytes(cp.bytes) 115 | constants.append(jint) 116 | elif isinstance(cp, FloatInfo): 117 | jfloat = JFloat() 118 | jfloat.data = common_utils.get_float_from_bytes(cp.bytes) 119 | constants.append(jfloat) 120 | elif isinstance(cp, LongInfo): 121 | jlong = JLong() 122 | jlong.data = common_utils.get_long_from_bytes(cp.high_bytes, cp.low_bytes) 123 | constants.append(jlong) 124 | elif isinstance(cp, DoubleInfo): 125 | jdouble = JDouble() 126 | jdouble.data = common_utils.get_double_from_bytes(cp.high_bytes, cp.low_bytes) 127 | constants.append(jdouble) 128 | elif isinstance(cp, NameAndTypeInfo): 129 | constants.append(None) 130 | elif isinstance(cp, Utf8Info): 131 | constants.append(common_utils.get_string_from_bytes(cp.bytes)) 132 | elif isinstance(cp, MethodHandleInfo): 133 | constants.append(None) 134 | else: 135 | constants.append(None) 136 | constants_pool = ConstantPool() 137 | constants_pool.constants = constants 138 | return constants_pool 139 | 140 | 141 | def get_attribute(attributes, constant_pool, name): 142 | for attr in attributes: 143 | index = common_utils.get_int_from_bytes(attr.attribute_name_index) 144 | aname = constant_pool[index] 145 | if aname == name: 146 | return attr 147 | 148 | return None 149 | 150 | 151 | class Field(object): 152 | def __init__(self): 153 | self.access_flag = None 154 | self.name = None 155 | self.descriptor = None 156 | self.descriptor_index = None 157 | self.constant_value_index = None 158 | self.signature = None # 记录范型变量 159 | self.type = None # JClass 160 | 161 | def is_public(self): 162 | return MemberRef.check_state(self.access_flag, FieldRef.ACC_PUBLIC) 163 | 164 | def is_protected(self): 165 | return MemberRef.check_state(self.access_flag, FieldRef.ACC_PROTECTED) 166 | 167 | def is_private(self): 168 | return MemberRef.check_state(self.access_flag, FieldRef.ACC_PRIVATE) 169 | 170 | def is_static(self): 171 | return MemberRef.check_state(self.access_flag, FieldRef.ACC_STATIC) 172 | 173 | def is_final(self): 174 | return MemberRef.check_state(self.access_flag, FieldRef.ACC_FINAL) 175 | 176 | def is_volatile(self): 177 | return MemberRef.check_state(self.access_flag, FieldRef.ACC_VOLATILE) 178 | 179 | def is_transient(self): 180 | return MemberRef.check_state(self.access_flag, FieldRef.ACC_TRANSIENT) 181 | 182 | @staticmethod 183 | def new_fields(cf_fields, constant_pool): 184 | fields = [] 185 | for f in cf_fields: 186 | nf = Field() 187 | nf.access_flag = common_utils.get_int_from_bytes(f.access_flags) 188 | nf.name = constant_pool[common_utils.get_int_from_bytes(f.name_index)] 189 | nf.descriptor_index = common_utils.get_int_from_bytes(f.descriptor_index) 190 | nf.descriptor = constant_pool[nf.descriptor_index] 191 | attr = get_attribute(f.attributes, constant_pool, 'ConstantValue') 192 | if attr is not None: 193 | nf.constant_value_index = common_utils.get_int_from_bytes(attr.constant_value_index) 194 | fields.append(nf) 195 | return fields 196 | 197 | 198 | class Method(object): 199 | def __init__(self): 200 | self.access_flag = None 201 | self.name = None 202 | self.descriptor = None 203 | self.max_stack = None 204 | self.max_locals = None 205 | self.code = None 206 | self.exceptions = None # ExceptionTable[] 207 | self.arg_desc = None 208 | self.jclass = None 209 | 210 | @staticmethod 211 | def new_methods(jclass, cf_methods, constant_pool): 212 | methods = [] 213 | for m in cf_methods: 214 | nm = Method() 215 | nm.jclass = jclass 216 | nm.access_flag = common_utils.get_int_from_bytes(m.access_flags) 217 | nm.name = constant_pool[common_utils.get_int_from_bytes(m.name_index)] 218 | nm.descriptor = constant_pool[common_utils.get_int_from_bytes(m.descriptor_index)] 219 | attr = get_attribute(m.attributes, constant_pool, 'Code') 220 | nm.max_stack = common_utils.get_int_from_bytes(attr.max_stack) 221 | nm.max_locals = common_utils.get_int_from_bytes(attr.max_locals) 222 | nm.code = attr.code 223 | nm.exceptions = [] 224 | for ex in attr.exception_table: 225 | jex = JException() 226 | jex.start_pc = common_utils.get_int_from_bytes(ex.start_pc) 227 | jex.end_pc = common_utils.get_int_from_bytes(ex.end_pc) 228 | jex.handler_pc = common_utils.get_int_from_bytes(ex.handler_pc) 229 | jex.catch_type = common_utils.get_int_from_bytes(ex.catch_type) 230 | nm.exceptions.append(jex) 231 | nm.arg_desc = Method.get_arg_desc(nm.descriptor) 232 | methods.append(nm) 233 | return methods 234 | 235 | @staticmethod 236 | def get_arg_desc(descs): 237 | arg_desc = [] 238 | desc = '' 239 | for s in descs: 240 | if s == ')': 241 | break 242 | if len(desc) == 0: 243 | if s == 'B' or s == 'C' or s == 'D' or s == 'F' or s == 'I' or s == 'J' or s == 'S' or s == 'Z': 244 | desc = s 245 | arg_desc.append(desc) 246 | desc = '' 247 | elif s == 'L': 248 | desc += s 249 | else: 250 | if desc[0] == 'L': 251 | desc += s 252 | if s == ';': 253 | arg_desc.append(desc) 254 | desc = '' 255 | elif desc[0] == '[': 256 | if 'L' in desc: 257 | desc += s 258 | if s == ';': 259 | arg_desc.append(desc) 260 | desc = '' 261 | else: 262 | desc += s 263 | if s != '[': 264 | arg_desc.append(desc) 265 | desc = '' 266 | return arg_desc 267 | 268 | 269 | class JException(object): 270 | def __init__(self): 271 | self.start_pc = 0 272 | self.end_pc = 0 273 | self.handler_pc = 0 274 | self.catch_type = 0 275 | 276 | 277 | class Ref(object): 278 | def __init__(self): 279 | self.cp = None 280 | self.class_name = None 281 | self.cache_class = None # JClass 282 | 283 | def resolve_class(self, class_loader, need_re_resolve=False, class_name=None): 284 | if self.cache_class is not None and not need_re_resolve: 285 | return self.cache_class 286 | if class_loader is None: 287 | class_loader = ClassLoader.default_class_loader() 288 | if class_name is None: 289 | class_name = self.class_name 290 | self.cache_class = class_loader.load_class(class_name) 291 | self.cache_class.class_loader = class_loader 292 | return self.cache_class 293 | 294 | 295 | class ClassRef(Ref): 296 | def __init__(self): 297 | super(ClassRef, self).__init__() 298 | 299 | @staticmethod 300 | def new_class_ref(cp, class_info): # ConstantPool ConstantClassInfo 301 | cr = ClassRef() 302 | cr.cp = cp 303 | tmp = cp[common_utils.get_int_from_bytes(class_info.name_index)] 304 | cr.class_name = common_utils.get_string_from_bytes(tmp.bytes) 305 | return cr 306 | 307 | 308 | class MemberRef(Ref): 309 | def __init__(self): 310 | super(MemberRef, self).__init__() 311 | self.name = None 312 | self.descriptor = None 313 | self.access_flag = None 314 | 315 | @staticmethod 316 | def check_state(flag, state): 317 | if flag is None: 318 | return False 319 | return (flag & state) != 0 320 | 321 | @staticmethod 322 | def get_string(cp, index_byte): 323 | return common_utils.get_string_from_bytes(cp[common_utils.get_int_from_bytes(index_byte)].bytes) 324 | 325 | @staticmethod 326 | def get_obj(cp, index_byte): 327 | return cp[common_utils.get_int_from_bytes(index_byte)] 328 | 329 | 330 | class FieldRef(MemberRef): 331 | ACC_PUBLIC = 0x0001 332 | ACC_PRIVATE = 0x0002 333 | ACC_PROTECTED = 0x0004 334 | ACC_STATIC = 0x0008 335 | ACC_FINAL = 0x0010 336 | ACC_VOLATILE = 0x0040 337 | ACC_TRANSIENT = 0x0080 338 | ACC_SYNTHETIC = 0x1000 339 | ACC_ENUM = 0x4000 340 | 341 | def __init__(self): 342 | super(FieldRef, self).__init__() 343 | self.field = None 344 | 345 | def is_public(self): 346 | return MemberRef.check_state(self.access_flag, FieldRef.ACC_PUBLIC) 347 | 348 | def is_protected(self): 349 | return MemberRef.check_state(self.access_flag, FieldRef.ACC_PROTECTED) 350 | 351 | def is_private(self): 352 | return MemberRef.check_state(self.access_flag, FieldRef.ACC_PRIVATE) 353 | 354 | def is_static(self): 355 | return MemberRef.check_state(self.access_flag, FieldRef.ACC_STATIC) 356 | 357 | def is_final(self): 358 | return MemberRef.check_state(self.access_flag, FieldRef.ACC_FINAL) 359 | 360 | def is_volatile(self): 361 | return MemberRef.check_state(self.access_flag, FieldRef.ACC_VOLATILE) 362 | 363 | def is_transient(self): 364 | return MemberRef.check_state(self.access_flag, FieldRef.ACC_TRANSIENT) 365 | 366 | @staticmethod 367 | def new_field_ref(cp, field_ref_info): 368 | fr = FieldRef() 369 | cl = cp[common_utils.get_int_from_bytes(field_ref_info.class_index)] 370 | fr.class_name = MemberRef.get_string(cp, cl.name_index) 371 | fr.cp = cp 372 | name_and_type = MemberRef.get_obj(cp, field_ref_info.name_and_type_index) 373 | fr.name = MemberRef.get_string(cp, name_and_type.name_index) 374 | fr.descriptor = MemberRef.get_string(cp, name_and_type.descriptor_index) 375 | return fr 376 | 377 | def resolve_field(self, class_loader): 378 | if self.field is not None: 379 | return self.field 380 | if self.cache_class is None: 381 | self.resolve_class(class_loader) 382 | fields = self.cache_class.fields 383 | for f in fields: 384 | if f.name == self.name: 385 | self.field = f 386 | break 387 | return self.field 388 | 389 | 390 | class MethodRef(MemberRef): 391 | def __init__(self): 392 | super(MethodRef, self).__init__() 393 | self.method = None 394 | 395 | @staticmethod 396 | def new_method_ref(cp, method_ref_info): 397 | mr = MethodRef() 398 | cl = cp[common_utils.get_int_from_bytes(method_ref_info.class_index)] 399 | mr.class_name = MemberRef.get_string(cp, cl.name_index) 400 | mr.cp = cp 401 | name_and_type = MemberRef.get_obj(cp, method_ref_info.name_and_type_index) 402 | mr.name = MemberRef.get_string(cp, name_and_type.name_index) 403 | mr.descriptor = MemberRef.get_string(cp, name_and_type.descriptor_index) 404 | return mr 405 | 406 | # TODO: 方法权限等的处理 407 | def resolve_method(self, class_loader, need_re_resolve=False, class_name=None): 408 | if self.method is not None and not need_re_resolve: 409 | return self.method 410 | if self.cache_class is None or need_re_resolve: 411 | self.resolve_class(class_loader, need_re_resolve, class_name) 412 | methods = self.cache_class.methods 413 | for m in methods: 414 | if m.name == self.name and m.descriptor == self.descriptor: 415 | self.method = m 416 | break 417 | return self.method 418 | 419 | def resolve_method_with_super(self, class_loader): 420 | self.resolve_method(class_loader, True) 421 | if self.method is None: 422 | super_class = self.cache_class.super_class 423 | while super_class is not None: 424 | for m in super_class.methods: 425 | if m.name == self.name: 426 | self.method = m 427 | break 428 | if self.method is not None: 429 | break 430 | super_class = super_class.super_class 431 | return self.method 432 | 433 | def re_resolve_method_with_super_by_class_name(self, class_loader, class_name): 434 | self.resolve_method(class_loader, True, class_name) 435 | if self.method is None: 436 | super_class = self.cache_class.super_class 437 | while super_class is not None: 438 | for m in super_class.methods: 439 | if m.name == self.name: 440 | self.method = m 441 | break 442 | if self.method is not None: 443 | break 444 | super_class = super_class.super_class 445 | return self.method 446 | 447 | 448 | class BaseType(object): 449 | def __init__(self): 450 | self.data = None 451 | 452 | 453 | class JInteger(BaseType): 454 | def __init__(self): 455 | super(JInteger, self).__init__() 456 | 457 | 458 | class JFloat(BaseType): 459 | def __init__(self): 460 | super(JFloat, self).__init__() 461 | 462 | 463 | class JLong(BaseType): 464 | def __init__(self): 465 | super(JLong, self).__init__() 466 | 467 | 468 | class JDouble(BaseType): 469 | def __init__(self): 470 | super(JDouble, self).__init__() 471 | 472 | 473 | class JString(BaseType): 474 | def __init__(self): 475 | super(JString, self).__init__() 476 | 477 | 478 | # TODO: 感觉还是应该分一个包出去 479 | class ClassLoader(object): 480 | default_loader = None 481 | 482 | def __init__(self): 483 | self._loading_classes = [] 484 | self._loaded_classes = {} 485 | self.pkg_path = jdk_path 486 | self.hack() 487 | 488 | def get_all_loaded_class(self): 489 | return self._loading_classes 490 | 491 | def hack(self): 492 | # 先提前 load 493 | self.load_class('java/lang/Object') 494 | 495 | @staticmethod 496 | def default_class_loader(): 497 | # TODO: 线程同步 498 | if ClassLoader.default_loader is None: 499 | ClassLoader.default_loader = ClassLoader() 500 | return ClassLoader.default_loader 501 | 502 | def add_path(self, path): 503 | self.pkg_path.append(path) 504 | 505 | # TODO: jar zip 处理 506 | def load_class(self, class_name): 507 | # TODO: load class 线程之间同步 暂时轮询 508 | if class_name in self._loading_classes: 509 | while True: 510 | if class_name not in self._loading_classes: 511 | break 512 | if class_name in self._loaded_classes: 513 | return self._loaded_classes[class_name] 514 | jclass = self.__load_class(class_name) 515 | self._loading_classes.remove(class_name) 516 | return jclass 517 | 518 | def __load_class(self, class_name): 519 | self._loading_classes.append(class_name) 520 | if class_name[0] == '[': 521 | return self.__load_array_class(class_name) 522 | for path in self.pkg_path: 523 | class_path = path + class_name.replace('.', '/') + '.class' 524 | if not os.path.exists(class_path): 525 | continue 526 | print_utils.print_jvm_status('load class: ' + class_path) 527 | jclass = self.define_class(class_name, class_path) 528 | self._loaded_classes[class_name] = jclass 529 | return jclass 530 | return None 531 | 532 | def __load_array_class(self, class_name): 533 | jclass = JClass() 534 | jclass.super_class_name = 'java/lang/Object' 535 | jclass.class_loader = self 536 | jclass.has_inited = True 537 | jclass.name = class_name 538 | self._loaded_classes[class_name] = jclass 539 | 540 | def define_class(self, class_name, path): 541 | parser = ClassParser(path) 542 | parser.parse() 543 | jclass = JClass() 544 | jclass.name = class_name 545 | jclass.new_jclass(parser.class_file) 546 | jclass.super_class = self.load_super_class(jclass) 547 | return jclass 548 | 549 | def load_super_class(self, jclass): 550 | if jclass.super_class_name == 'java/lang/Object' or jclass.super_class_name is None: 551 | return 552 | return self.load_class(jclass.super_class_name) 553 | -------------------------------------------------------------------------------- /runtime/jobject.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | 3 | from runtime.thread import Slot 4 | from base.utils import error_handler 5 | import runtime.heap as heap 6 | 7 | 8 | # 对应 java 中的实例对象 9 | class JObject(object): 10 | TYPE_OBJ = 0 11 | TYPE_ARRAY = 1 12 | 13 | def __init__(self): 14 | self.type = JObject.TYPE_OBJ 15 | self.jclass = None 16 | self.data = None # 在 JObject 是map,在 JAarry 里面是 Slot 数组 17 | 18 | @staticmethod 19 | def new_object(jclass): 20 | jobject = JObject() 21 | jobject.type = JObject.TYPE_OBJ 22 | jobject.jclass = jclass 23 | jobject.data = {} 24 | JObject.collect_fields(jobject.jclass, jobject.data, False) 25 | 26 | # 收集父类 field 27 | super_class = jobject.jclass.super_class 28 | while super_class is not None: 29 | JObject.collect_fields(super_class, jobject.data, True) 30 | super_class = super_class.super_class 31 | return jobject 32 | 33 | @staticmethod 34 | def collect_fields(jclass, data, filter_private): 35 | for field in jclass.get_instance_fields(): 36 | if filter_private and field.is_private(): 37 | continue 38 | desc = field.descriptor 39 | slot = Slot() 40 | if desc == 'B' or desc == 'I' or desc == 'J' or desc == 'S' or desc == 'Z': 41 | slot.num = 0 42 | elif desc == 'C': 43 | slot.num = '0' 44 | elif desc == 'F': 45 | slot.num = 0.0 46 | elif desc == 'D': 47 | slot.num = 0.0 48 | data[field.name] = slot 49 | 50 | def get_field(self, name): 51 | self.__check_name(name) 52 | slot = self.data[name] 53 | if slot.num is not None: 54 | return slot.num 55 | return slot.ref 56 | 57 | def put_field(self, name, num): 58 | self.__check_name(name) 59 | self.data[name].num = num 60 | 61 | def put_ref_field(self, name, ref): 62 | self.__check_name(name) 63 | self.data[name].ref = ref 64 | 65 | def __check_name(self, name): 66 | if name not in self.data: 67 | error_handler.rise_runtime_error('no this field') 68 | 69 | 70 | # 指向实例对象 71 | # 实例对象保存在 gc 堆中,ref 指向实例对象 72 | class JRef(object): 73 | def __init__(self, obj): 74 | self.handler = JHandler(obj) 75 | 76 | @staticmethod 77 | def check_null(jref): 78 | if jref is not None and jref.handler is not None and jref.handler.obj is not None: 79 | return False 80 | return True 81 | 82 | @staticmethod 83 | def new_object(jclass): 84 | # TODO: obj 放入 gc 堆 85 | obj = JObject.new_object(jclass) 86 | jref = JRef(obj) 87 | heap.Heap.new_ref(jref) 88 | return jref 89 | 90 | @staticmethod 91 | def new_array(jclass, atype, count): 92 | array = JArray.new_array(jclass, atype, count) 93 | jref = JRef(array) 94 | heap.Heap.new_ref(jref) 95 | return jref 96 | 97 | @staticmethod 98 | def new_ref_array(jclass, type_class_ref, count): 99 | array = JArray.new_ref_array(jclass, type_class_ref, count) 100 | jref = JRef(array) 101 | heap.Heap.new_ref(jref) 102 | return jref 103 | 104 | def clone(self): 105 | return JRef(self.handler.obj) 106 | 107 | 108 | # 方便 gc 109 | class JHandler(object): 110 | def __init__(self, obj): 111 | self.obj = obj 112 | 113 | 114 | class JArray(JObject): 115 | T_BOOLEAN = 4 116 | T_CHAR = 5 117 | T_FLOAT = 6 118 | T_DOUBLE = 7 119 | T_BYTE = 8 120 | T_SHORT = 9 121 | T_INT = 10 122 | T_LONG = 11 123 | 124 | T_REF = 100 125 | 126 | def __init__(self): 127 | super(JArray, self).__init__() 128 | self.atype = None 129 | self.length = 0 130 | self.descriptor = '' 131 | 132 | def add_item(self, index, item): 133 | self.__check_index(index) 134 | self.data[index].num = item 135 | 136 | def add_ref_item(self, index, item): 137 | self.__check_index(index) 138 | self.data[index].ref = item 139 | 140 | def get_item(self, index): 141 | self.__check_index(index) 142 | slot = self.data[index] 143 | if slot.num is not None: 144 | return slot.num 145 | return slot.ref 146 | 147 | def __check_index(self, index): 148 | if index >= self.length: 149 | error_handler.rise_runtime_error('index out of bounds') 150 | 151 | @staticmethod 152 | def get_array_jclass_name(atype): 153 | if atype == JArray.T_BOOLEAN: 154 | return '[Z' 155 | elif atype == JArray.T_CHAR: 156 | return '[C' 157 | elif atype == JArray.T_FLOAT: 158 | return '[F' 159 | elif atype == JArray.T_DOUBLE: 160 | return '[D' 161 | elif atype == JArray.T_BYTE: 162 | return '[B' 163 | elif atype == JArray.T_SHORT: 164 | return '[S' 165 | elif atype == JArray.T_INT: 166 | return '[I' 167 | elif atype == JArray.T_LONG: 168 | return '[J' 169 | return '' 170 | 171 | @staticmethod 172 | def get_ref_array_jclass_name(ref_desc): 173 | return '[' + ref_desc 174 | 175 | @staticmethod 176 | def new_array(jclass, atype, length): 177 | jarray = JArray() 178 | jarray.type = JObject.TYPE_ARRAY 179 | jarray.jclass = jclass 180 | jarray.length = length 181 | jarray.atype = atype 182 | jarray.descriptor = JArray.get_array_jclass_name(atype) 183 | jarray.data = [] 184 | for i in range(length): 185 | jarray.data.append(Slot()) 186 | return jarray 187 | 188 | @staticmethod 189 | def new_ref_array(jclass, type_class_ref, length): 190 | jarray = JArray() 191 | jarray.type = JObject.TYPE_ARRAY 192 | jarray.jclass = jclass 193 | jarray.length = length 194 | jarray.atype = JArray.T_REF 195 | jarray.descriptor = JArray.get_ref_array_jclass_name(type_class_ref.class_name) 196 | jarray.data = [] 197 | for i in range(length): 198 | jarray.data.append(Slot()) 199 | return jarray 200 | -------------------------------------------------------------------------------- /runtime/thread.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | 3 | from base.stack import Stack 4 | from base.utils.print_utils import print_jvm_status 5 | import runtime 6 | import struct 7 | 8 | 9 | # 这个 thread 是抽象的 thread 10 | class Thread(object): 11 | __thread_pool = [] 12 | 13 | def __init__(self): 14 | self.pc = 0 15 | self.stack = JavaStack() 16 | 17 | @staticmethod 18 | def new_thread(): 19 | t = Thread() 20 | Thread.__thread_pool.append(t) 21 | return t 22 | 23 | @staticmethod 24 | def finish_thread(t): 25 | Thread.__thread_pool.remove(t) 26 | 27 | @staticmethod 28 | def all_thread(): 29 | return Thread.__thread_pool 30 | 31 | def add_frame(self, frame): 32 | self.stack.add_frame(frame) 33 | 34 | def top_frame(self): 35 | return self.stack.top_frame() 36 | 37 | def pop_frame(self): 38 | self.stack.pop_frame() 39 | 40 | def has_frame(self): 41 | return self.stack.has_frame() 42 | 43 | def all_frames(self): 44 | return self.stack.all_frames() 45 | 46 | 47 | class JavaStack(object): 48 | def __init__(self): 49 | self.__frames = [] 50 | 51 | def has_frame(self): 52 | return len(self.__frames) > 0 53 | 54 | def add_frame(self, frame): 55 | self.__frames.append(frame) 56 | 57 | def pop_frame(self): 58 | self.__frames.pop() 59 | 60 | def top_frame(self): 61 | return self.__frames[len(self.__frames) - 1] 62 | 63 | def all_frames(self): 64 | return self.__frames 65 | 66 | 67 | class Frame(object): 68 | def __init__(self, thread, method): 69 | self.pc = 0 70 | self.thread = thread 71 | self.method = method 72 | self.max_stack = method.max_stack 73 | self.max_locals = method.max_locals 74 | self.operand_stack = OperandStack(self.max_stack) 75 | self.local_vars = LocalVars(self.max_locals) 76 | self.dynamic_linking = DynamicLinking() 77 | 78 | def print_cur_state(self): 79 | print_jvm_status('max_stack: ' + str(self.max_stack)) 80 | print_jvm_status('max_locals: ' + str(self.max_locals)) 81 | print_jvm_status('operand_stack: ' + str(self.operand_stack.size())) 82 | print_jvm_status(self.operand_stack) 83 | print_jvm_status('local_vars: ' + str(self.local_vars.size())) 84 | print_jvm_status(self.local_vars) 85 | 86 | 87 | class Slot(object): 88 | def __init__(self): 89 | self.num = None 90 | self.ref = None 91 | 92 | 93 | # 局部变量表 94 | class LocalVars(object): 95 | def __init__(self, size): 96 | self.__size = size 97 | self.__items = [None] * size 98 | for i in range(size): 99 | self.__items[i] = Slot() 100 | 101 | def __str__(self): 102 | s = '' 103 | for i in self.__items: 104 | s += str(i) 105 | s += '\n' 106 | return s 107 | 108 | def size(self): 109 | return self.__size 110 | 111 | def print_state(self): 112 | print_jvm_status(self.__items) 113 | 114 | def get_items(self): 115 | return self.__items 116 | 117 | def __add_num_to_item(self, index, data): 118 | slot = self.__items[index] 119 | slot.num = data 120 | 121 | def __get_num_from_item(self, index): 122 | return self.__items[index].num 123 | 124 | def __add_ref_to_item(self, index, ref): 125 | slot = self.__items[index] 126 | slot.ref = ref 127 | 128 | def __get_ref_from_item(self, index): 129 | return self.__items[index].ref 130 | 131 | def add_int(self, index, data): 132 | self.__add_num_to_item(index, struct.pack('i', data)) 133 | 134 | def get_int(self, index): 135 | return struct.unpack('i', self.__get_num_from_item(index))[0] 136 | 137 | def add_long(self, index, data): 138 | packed = struct.pack('q', data) 139 | self.__add_num_to_item(index, packed[:4]) 140 | self.__add_num_to_item(index + 1, packed[4:]) 141 | 142 | def get_long(self, index): 143 | first = self.__get_num_from_item(index) 144 | last = self.__get_num_from_item(index + 1) 145 | return struct.unpack('q', first + last)[0] 146 | 147 | # TODO: python3 里 float 也是 8 字节,float 精度存疑 148 | def add_float(self, index, data): 149 | self.__add_num_to_item(index, struct.pack('f', data)) 150 | 151 | def get_float(self, index): 152 | return struct.unpack('f', self.__get_num_from_item(index))[0] 153 | 154 | def add_double(self, index, data): 155 | packed = struct.pack('d', data) 156 | self.__add_num_to_item(index, packed[:4]) 157 | self.__add_num_to_item(index + 1, packed[4:]) 158 | 159 | def get_double(self, index): 160 | first = self.__get_num_from_item(index) 161 | last = self.__get_num_from_item(index + 1) 162 | return struct.unpack('d', first + last)[0] 163 | 164 | def add_ref(self, index, ref): 165 | self.__add_ref_to_item(index, ref) 166 | 167 | def get_ref(self, index): 168 | return self.__get_ref_from_item(index) 169 | 170 | 171 | class Entry(object): 172 | def __init__(self, data): 173 | self.data = data 174 | 175 | def __str__(self): 176 | return str(self.data) 177 | 178 | 179 | # 操作数栈 180 | class OperandStack(object): 181 | def __init__(self, size): 182 | self.__size = size 183 | self.__stack = Stack() 184 | 185 | def size(self): 186 | return self.__size 187 | 188 | def print_state(self): 189 | self.__stack.print_state() 190 | 191 | def clear(self): 192 | self.__stack.clear() 193 | 194 | # !!! notice !!! 如果是非 jref 的数据,这个方法返回的是封装后的 eg: int 返回的实际是 JInteger 主要是方便 push 使用 195 | # 如果以后需要真实数据,再改吧 196 | def top(self, index=None): 197 | if index is None: 198 | return self.__stack.peek().data 199 | else: 200 | return self.__stack.get_val_at(index).data 201 | 202 | # 类型1 指的是占一个 slot 的类型: int, float, ref 203 | def is_top_type1(self, index=None): 204 | ref = None 205 | if index is None: 206 | ref = self.__stack.peek().data 207 | else: 208 | ref = self.__stack.get_val_at(index).data 209 | if isinstance(ref, runtime.jclass.JInteger) or isinstance(ref, runtime.jclass.JFloat) \ 210 | or isinstance(ref, runtime.jclass.JRef): 211 | return True 212 | return False 213 | 214 | def push(self, data): 215 | entry = Entry(data) 216 | self.__stack.push(entry) 217 | 218 | def pop(self): 219 | ref = self.__stack.pop().data 220 | if isinstance(ref, runtime.jclass.JInteger) or isinstance(ref, runtime.jclass.JFloat) \ 221 | or isinstance(ref, runtime.jclass.JLong) or isinstance(ref, runtime.jclass.JDouble): 222 | return ref.data 223 | return ref 224 | 225 | def pop_raw(self): 226 | return self.__stack.pop().data 227 | 228 | def push_int(self, data): 229 | jint = runtime.jclass.JInteger() 230 | jint.data = data 231 | self.push(jint) 232 | 233 | def pop_int(self): 234 | return self.pop() 235 | 236 | def push_long(self, data): 237 | jlong = runtime.jclass.JLong() 238 | jlong.data = data 239 | self.push(jlong) 240 | 241 | def pop_long(self): 242 | return self.pop() 243 | 244 | def push_float(self, data): 245 | jfloat = runtime.jclass.JFloat() 246 | jfloat.data = data 247 | self.push(jfloat) 248 | 249 | def pop_float(self): 250 | return self.pop() 251 | 252 | def push_double(self, data): 253 | jdouble = runtime.jclass.JDouble() 254 | jdouble.data = data 255 | self.push(jdouble) 256 | 257 | def pop_double(self): 258 | return self.pop() 259 | 260 | def push_ref(self, ref): 261 | self.push(ref) 262 | 263 | def pop_ref(self): 264 | return self.pop() 265 | 266 | def get_all_data(self): 267 | return self.__stack.items() 268 | 269 | def __str__(self): 270 | s = '' 271 | for i in self.__stack.items(): 272 | s += str(i) 273 | s += '\n' 274 | return s 275 | 276 | 277 | class DynamicLinking(object): 278 | def __init__(self): 279 | pass 280 | 281 | 282 | def test_local_var(): 283 | local_vars = LocalVars(9) 284 | local_vars.add_long(0, 2147483680) 285 | print(local_vars.get_long(0)) 286 | 287 | local_vars.add_int(2, 8) 288 | print(local_vars.get_int(2)) 289 | 290 | local_vars.add_double(3, 2147483680.1231231312) 291 | print(local_vars.get_double(3)) 292 | 293 | local_vars.add_float(5, 8.111) 294 | print(local_vars.get_float(5)) 295 | 296 | 297 | def test_main(): 298 | pass 299 | 300 | 301 | if __name__ == "__main__": 302 | test_local_var() 303 | # test_main() 304 | -------------------------------------------------------------------------------- /test/Hello$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/5A59/Zvm/d093558c567488472252a4f6f87cecbc0ec2bd38/test/Hello$1.class -------------------------------------------------------------------------------- /test/Hello$NOT.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/5A59/Zvm/d093558c567488472252a4f6f87cecbc0ec2bd38/test/Hello$NOT.class -------------------------------------------------------------------------------- /test/Hello$T.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/5A59/Zvm/d093558c567488472252a4f6f87cecbc0ec2bd38/test/Hello$T.class -------------------------------------------------------------------------------- /test/Hello$T1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/5A59/Zvm/d093558c567488472252a4f6f87cecbc0ec2bd38/test/Hello$T1.class -------------------------------------------------------------------------------- /test/Hello$T2.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/5A59/Zvm/d093558c567488472252a4f6f87cecbc0ec2bd38/test/Hello$T2.class -------------------------------------------------------------------------------- /test/Hello$TestException.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/5A59/Zvm/d093558c567488472252a4f6f87cecbc0ec2bd38/test/Hello$TestException.class -------------------------------------------------------------------------------- /test/Hello.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/5A59/Zvm/d093558c567488472252a4f6f87cecbc0ec2bd38/test/Hello.class -------------------------------------------------------------------------------- /test/Hello.java: -------------------------------------------------------------------------------- 1 | public class Hello { 2 | static final int finalVaule = 13; 3 | static int staticValue = 12; 4 | int tmp = 0; 5 | public static void main(String[] args) { 6 | System.out.println("================="); 7 | System.out.println("Hello world"); 8 | System.out.println("================="); 9 | testPrint(); 10 | test(); 11 | testBase(); 12 | testArray(); 13 | testThread(); 14 | testClass(); 15 | checkCast(); 16 | 17 | // checkNull(); 18 | 19 | testGC(); 20 | testSwitch(); 21 | testReturn(); 22 | // testException(); 23 | } 24 | 25 | public static void testException() { 26 | System.out.println("======== test exception ========="); 27 | try { 28 | testException1(); 29 | } catch(Exception ex) { 30 | System.out.println("exception catched"); 31 | } 32 | } 33 | 34 | public static void testException1() throws TestException { 35 | throw new TestException(); 36 | } 37 | 38 | public static void testPrint() { 39 | System.out.println("======== test print ========="); 40 | System.out.println(1); 41 | } 42 | 43 | public static void testReturn() { 44 | System.out.println("======== test return ========="); 45 | System.out.println(-100); 46 | T t = newT(); 47 | System.out.println(t.n); 48 | int i = returnI(); 49 | System.out.println(i); 50 | double d = returnD(); 51 | System.out.println(d); 52 | float f = returnF(); 53 | System.out.println(f); 54 | long l = returnL(); 55 | System.out.println(l); 56 | } 57 | 58 | public static void testSwitch() { 59 | System.out.println("======== test switch ========="); 60 | int i = 1; 61 | int b = switchTest(i); 62 | System.out.println(b); 63 | b = switchTest(2); 64 | System.out.println(b); 65 | b = switchTest(0); 66 | System.out.println(b); 67 | b = switchTest(5); 68 | System.out.println(b); 69 | 70 | System.out.println("============="); 71 | b = lookUpSwitchTest(-100); 72 | System.out.println(b); 73 | b = lookUpSwitchTest(1); 74 | System.out.println(b); 75 | b = lookUpSwitchTest(100); 76 | System.out.println(b); 77 | b = lookUpSwitchTest(20); 78 | System.out.println(b); 79 | } 80 | 81 | public static void testGC() { 82 | System.out.println("======== test gc ========="); 83 | testGC2(); 84 | for (int i = 0; i < 9; i ++) { 85 | T t = new T(); 86 | } 87 | } 88 | 89 | public static void testGC2() { 90 | for (int i = 0; i < 9; i ++) { 91 | T t = new T(); 92 | } 93 | } 94 | 95 | public static void testClass() { 96 | System.out.println("======== test class ========="); 97 | T t = new T(); 98 | t.m = 1; 99 | t.not.n = 3; 100 | System.out.println(t.m); 101 | t.test1(); 102 | 103 | T1 t1 = new T(); 104 | T1 t2 = new T1(); 105 | } 106 | 107 | public static void testThread() { 108 | System.out.println("======== test thread ========="); 109 | Thread thread = new Thread() { 110 | public void run() { 111 | for (int i = 0; i < 10; i ++) { 112 | System.out.println("in thread"); 113 | System.out.println(i); 114 | } 115 | } 116 | }; 117 | thread.start(); 118 | 119 | for (int i = 0; i < 10; i ++) { 120 | System.out.println("in main thread"); 121 | } 122 | } 123 | 124 | public static void testBase() { 125 | System.out.println("======== test base type ========="); 126 | char c = 'c'; 127 | System.out.println(c); 128 | 129 | long a = 100l; 130 | System.out.println(a); 131 | double d = 12.5; 132 | System.out.println(d); 133 | float f = 11.6f; 134 | System.out.println(f); 135 | short s = 129; 136 | System.out.println(s); 137 | byte bb = 8; 138 | System.out.println(bb); 139 | boolean b = true; 140 | boolean cc = false; 141 | System.out.println(b); 142 | System.out.println(cc); 143 | } 144 | 145 | public static void test() { 146 | System.out.println("======== test operation ========"); 147 | System.out.println("hello"); 148 | int res = 1; 149 | int i = 10; 150 | T t = new T(); 151 | res = t.test(res); 152 | res = add(i, 2); 153 | res = t.test(res); 154 | System.out.println(res); 155 | System.out.println(1); 156 | System.out.println(1 + 1); 157 | System.out.println(2 - 1); 158 | System.out.println(3 << 1); 159 | System.out.println(3 >> 1); 160 | System.out.println(2 ^ 1); 161 | System.out.println(1 | 1); 162 | System.out.println(2 & 1); 163 | } 164 | 165 | public static void checkNull() { 166 | System.out.println("======== test null check ========"); 167 | T t = null; 168 | System.out.println(t.m); 169 | if (t == null) { 170 | t = new T(); 171 | System.out.println(t.m); 172 | } 173 | } 174 | 175 | public static void checkCast() { 176 | System.out.println("======== test cast ========"); 177 | T1 t = new T(); 178 | if (t instanceof T) { 179 | T t1 = (T) t; 180 | System.out.println("instance of 1"); 181 | } 182 | T2 t2 = new T2(); 183 | if (t2 instanceof T) { 184 | T t1 = (T) t; 185 | System.out.println("instance of"); 186 | } 187 | } 188 | 189 | public static void testArray() { 190 | System.out.println("======== test array ========"); 191 | int[] array = {3, 4}; 192 | System.out.println(array[0]); 193 | System.out.println(array.length); 194 | int[] a1 = new int[2]; 195 | a1[0] = 3; 196 | System.out.println(a1[0]); 197 | boolean[] bbarray = {true, false}; 198 | System.out.println(bbarray[0]); 199 | short[] sarray = {12, 15}; 200 | System.out.println(sarray[0]); 201 | byte[] barray = {1, 8}; 202 | System.out.println(barray[0]); 203 | float[] farray = {12.1f, 13.5f}; 204 | System.out.println(farray[0]); 205 | double[] darray = {12.121, 13.5}; 206 | System.out.println(darray[0]); 207 | long[] larray = {123213, 123432}; 208 | System.out.println(larray[0]); 209 | char[] carray = {'a', 'b'}; 210 | System.out.println(carray[0]); 211 | 212 | T[] tarray = new T[3]; 213 | tarray[0] = new T(); 214 | tarray[0].m = 3; 215 | System.out.println(tarray[0].m); 216 | } 217 | 218 | public static T newT() { 219 | return new T(); 220 | } 221 | 222 | public static int returnI() { 223 | return 1; 224 | } 225 | 226 | public static float returnF() { 227 | return 1.0f; 228 | } 229 | 230 | public static double returnD() { 231 | return 1.0; 232 | } 233 | 234 | public static long returnL() { 235 | return 1l; 236 | } 237 | 238 | public static int switchTest(int i) { 239 | switch(i) { 240 | case 0: return 0; 241 | case 1: return 1; 242 | case 2: return 2; 243 | default: return -1; 244 | } 245 | } 246 | 247 | public static int lookUpSwitchTest(int i) { 248 | switch(i) { 249 | case -100: return -100; 250 | case 1: return 1; 251 | case 100: return 100; 252 | default: return -1; 253 | } 254 | } 255 | 256 | public static int add(int i, int j) { 257 | return i + j; 258 | } 259 | 260 | public static class NOT { 261 | public int n = 0; 262 | } 263 | 264 | public static class T extends T1 { 265 | public static NOT not = new NOT(); 266 | public static int s = 3; 267 | public int n = 3; 268 | public int test(int i) { 269 | m = 3; 270 | return 1 + i; 271 | } 272 | 273 | public void test1() { 274 | super.test1(); 275 | System.out.println("class T method test1"); 276 | } 277 | } 278 | 279 | public static class T1 extends T2{ 280 | public int m; 281 | public void test1() { 282 | System.out.println("super class T1 method test1"); 283 | } 284 | } 285 | 286 | public static class T2 { 287 | public void test1() { 288 | System.out.println("super class T2 method test1"); 289 | } 290 | 291 | public void test2() { 292 | System.out.println("super class T2 method test2"); 293 | } 294 | } 295 | 296 | public static class TestException extends RuntimeException { 297 | } 298 | } 299 | -------------------------------------------------------------------------------- /test/Main.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/5A59/Zvm/d093558c567488472252a4f6f87cecbc0ec2bd38/test/Main.class -------------------------------------------------------------------------------- /test/Main.java: -------------------------------------------------------------------------------- 1 | public class Main { 2 | public static void main(String[] args) { 3 | System.out.println("Hello World !!!"); 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/java/io/PrintStream.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/5A59/Zvm/d093558c567488472252a4f6f87cecbc0ec2bd38/test/java/io/PrintStream.class -------------------------------------------------------------------------------- /test/java/io/PrintStream.java: -------------------------------------------------------------------------------- 1 | package java.io; 2 | 3 | public class PrintStream { 4 | 5 | public PrintStream println(String format) { 6 | return this; 7 | } 8 | 9 | public PrintStream println(long format) { 10 | return this; 11 | } 12 | 13 | public PrintStream println(boolean format) { 14 | return this; 15 | } 16 | 17 | public PrintStream println(int format) { 18 | return this; 19 | } 20 | 21 | public PrintStream println(double format) { 22 | return this; 23 | } 24 | 25 | public PrintStream println(float format) { 26 | return this; 27 | } 28 | 29 | public PrintStream println(short format) { 30 | return this; 31 | } 32 | 33 | public PrintStream println(byte format) { 34 | return this; 35 | } 36 | 37 | public PrintStream println(char format) { 38 | return this; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /test/java/lang/Exception.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/5A59/Zvm/d093558c567488472252a4f6f87cecbc0ec2bd38/test/java/lang/Exception.class -------------------------------------------------------------------------------- /test/java/lang/Exception.java: -------------------------------------------------------------------------------- 1 | package java.lang; 2 | 3 | public class Exception extends Throwable { 4 | } 5 | -------------------------------------------------------------------------------- /test/java/lang/Object.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/5A59/Zvm/d093558c567488472252a4f6f87cecbc0ec2bd38/test/java/lang/Object.class -------------------------------------------------------------------------------- /test/java/lang/Object.java: -------------------------------------------------------------------------------- 1 | package java.lang; 2 | 3 | public class Object { 4 | } 5 | -------------------------------------------------------------------------------- /test/java/lang/RuntimeException.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/5A59/Zvm/d093558c567488472252a4f6f87cecbc0ec2bd38/test/java/lang/RuntimeException.class -------------------------------------------------------------------------------- /test/java/lang/RuntimeException.java: -------------------------------------------------------------------------------- 1 | package java.lang; 2 | 3 | public class RuntimeException extends Exception { 4 | } 5 | -------------------------------------------------------------------------------- /test/java/lang/System.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/5A59/Zvm/d093558c567488472252a4f6f87cecbc0ec2bd38/test/java/lang/System.class -------------------------------------------------------------------------------- /test/java/lang/System.java: -------------------------------------------------------------------------------- 1 | package java.lang; 2 | 3 | import java.io.PrintStream; 4 | 5 | public class System { 6 | public final static PrintStream out = null; 7 | } 8 | -------------------------------------------------------------------------------- /test/java/lang/Thread.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/5A59/Zvm/d093558c567488472252a4f6f87cecbc0ec2bd38/test/java/lang/Thread.class -------------------------------------------------------------------------------- /test/java/lang/Thread.java: -------------------------------------------------------------------------------- 1 | package java.lang; 2 | 3 | public class Thread { 4 | public void start() { 5 | } 6 | 7 | public void run() { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /test/java/lang/Throwable.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/5A59/Zvm/d093558c567488472252a4f6f87cecbc0ec2bd38/test/java/lang/Throwable.class -------------------------------------------------------------------------------- /test/java/lang/Throwable.java: -------------------------------------------------------------------------------- 1 | package java.lang; 2 | 3 | public class Throwable { 4 | } 5 | -------------------------------------------------------------------------------- /test/test.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | 3 | from runtime.jclass import ClassLoader 4 | from runtime.jclass import JClass 5 | from interpreter import interpreter 6 | 7 | 8 | def main(): 9 | loader = ClassLoader() 10 | j_class = loader.load_class('Hello') 11 | print(j_class) 12 | method = j_class.get_main_method() 13 | interpreter.Interpreter.exec_method(method) 14 | 15 | if __name__ == '__main__': 16 | main() 17 | --------------------------------------------------------------------------------