def doubleToRawLongBits(frame: Frame): """ public static native long doubleToRawLongBits(double value); (D)J :param frame: :return: """ value = frame.local_vars.get_double(0) s = struct.pack('>d', value) bits = struct.unpack('>q', s)[0] frame.operand_stack.push_numeric(bits) def longBitsToDouble(frame: Frame): """ public static native double longBitsToDouble(long bits); (J)D :param frame: :return: """ bits = frame.local_vars.get_numeric(0) s = struct.pack('>q', bits) value = struct.unpack('>d', s)[0] frame.operand_stack.push_double(value) jlDouble = "java/lang/Double" register(jlDouble, "doubleToRawLongBits", "(D)J", doubleToRawLongBits) register(jlDouble, "longBitsToDouble", "(J)D", longBitsToDouble)
def floatToRawIntBits(frame: Frame): """ public static native int floatToRawIntBits(float value); (F)I :param frame: :return: """ value = frame.local_vars.get_float(0) s = struct.pack('>f', value) bits = struct.unpack('>l', s)[0] frame.operand_stack.push_numeric(ctypes.c_int32(bits).value) def intBitsToFloat(frame: Frame): """ public static native float intBitsToFloat(int bits); (I)F :param frame: :return: """ bits = frame.local_vars.get_numeric(0) s = struct.pack('>l', ctypes.c_uint32(bits).value) value = struct.unpack('>f', s)[0] frame.operand_stack.push_float(value) jlFloat = "java/lang/Float" register(jlFloat, "floatToRawIntBits", "(F)I", floatToRawIntBits) register(jlFloat, "intBitsToFloat", "(I)F", intBitsToFloat)
#!/usr/bin/env python # encoding: utf-8 """ @author: HuRuiFeng @file: VM.py @time: 2019/9/21 15:31 @desc: VM """ from ch10.instructions.base import MethodInvokeLogic from ch10.native.Registry import register from ch10.rtda.Frame import Frame from ch10.rtda.heap import StringPool def initialize(frame: Frame): vm_class = frame.method.get_class() saved_props = vm_class.get_ref_var("savedProps", "Ljava/util/Properties;") key = StringPool.j_string(vm_class.loader, "foo") val = StringPool.j_string(vm_class.loader, "bar") frame.operand_stack.push_ref(saved_props) frame.operand_stack.push_ref(key) frame.operand_stack.push_ref(val) props_class = vm_class.loader.load_class("java/util/Properties") set_prop_method = props_class.get_instance_method( "setProperty", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;") MethodInvokeLogic.invoke_method(frame, set_prop_method) register("sun/misc/VM", "initialize", "()V", initialize)
:param frame: :return: """ # 从局部变量表中拿到this引用 this = frame.local_vars.get_this() # 有了this引用,通过get_class()方法拿到它的Class对象,通过j_class属性拿到类对象 clazz = this.get_class().j_class # 把类对象推入操作数栈顶 frame.operand_stack.push_ref(clazz) def hash_code(frame: Frame): this = frame.local_vars.get_this() hash_value = hash(this) frame.operand_stack.push_numeric(hash_value) def clone(frame: Frame): this = frame.local_vars.get_this() cloneable = this.get_class().loader.load_class("java/lang/Cloneable") if not this.get_class().is_implements(cloneable): raise RuntimeError("java.lang.CloneNotSupportedException") frame.operand_stack.push_ref(this.clone()) jlObject = 'java/lang/Object' register(jlObject, 'getClass', '()Ljava/lang/Class;', get_class) register(jlObject, "hashCode", "()I", hash_code) register(jlObject, "clone", "()Ljava/lang/Object;", clone)
return stes # 计算所需跳过的帧数 def distance_to_object(clazz: Class): distance = 0 c = clazz.super_class while c is not None: distance += 1 c = c.super_class return distance # 根据帧创建StackTraceElement实例 def create_stack_trace_element(frame): method = frame.method clazz = method.get_class() stack_trace_element = StackTraceElement() stack_trace_element.file_name = clazz.source_file stack_trace_element.class_name = clazz.java_name stack_trace_element.method_name = method.name stack_trace_element.line_number = method.get_line_number(frame.next_pc - 1) return stack_trace_element jlThrowable = "java/lang/Throwable" register(jlThrowable, "fillInStackTrace", "(I)Ljava/lang/Throwable;", fill_in_stack_trace)
#!/usr/bin/env python # encoding: utf-8 """ @author: HuRuiFeng @file: String.py @time: 2019/9/21 10:56 @desc: java.lang.String类 """ from ch10.native.Registry import register from ch10.rtda.Frame import Frame from ch10.rtda.heap import StringPool def intern(frame: Frame): this = frame.local_vars.get_this() interned = StringPool.intern_string(this) frame.operand_stack.push_ref(interned) register("java/lang/String", "intern", "()Ljava/lang/String;", intern)
# 从局部变量表中拿到this引用,这是一个类对象引用 this = frame.local_vars.get_this() # 通过extra获得与之对应的Class对象 clazz = this.extra # 获取类名 name = clazz.java_name # 转成Java字符串 name_obj = j_string(clazz.loader, name) # 将其推入操作数栈顶 frame.operand_stack.push_ref(name_obj) def desired_assertion_status_0(frame: Frame): """ private static native boolean desiredAssertionStatus0(Class<?> clazz); :param frame: :return: """ # 把false推入操作数栈顶 frame.operand_stack.push_boolean(False) pass register("java/lang/Class", "getPrimitiveClass", "(Ljava/lang/String;)Ljava/lang/Class;", get_primitive_class) register("java/lang/Class", "getName0", "()Ljava/lang/String;", get_name_0) register("java/lang/Class", "desiredAssertionStatus0", "(Ljava/lang/Class;)Z", desired_assertion_status_0)
if src is None and dest is None: raise RuntimeError("java.lang.NullPointerException") # 源数据和目标数据必须兼容才能拷贝,否则抛出ArrayStoreException异常 if not check_array_copy(src, dest): raise RuntimeError("java.lang.ArrayStoreException") # 检查src_pos、dest_pos和length参数,有问题则抛出IndexOutOfBoundsException异常 if src_pos < 0 or dest_pos < 0 or length < 0 \ or src_pos + length > src.array_length() \ or dest_pos + length > dest.array_length(): raise RuntimeError("java.lang.IndexOutOfBoundsException") Object.array_copy(src, dest, src_pos, dest_pos, length) def check_array_copy(src, dest) -> bool: src_class = src.get_class() dest_class = dest.get_class() # 确保src和dest都是数组 if not src_class.is_array() or not dest_class.is_array(): return False # 检查数组类型,如果两者都是引用数组,则可以拷贝,否则两者必须是相同类型的基本类型数组 if src_class.component_class().is_primitive() or dest_class.component_class().is_primitive(): return src_class == dest_class return True register("java/lang/System", "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V", arraycopy)