func createStackTraceElements(tObj *heap.Object, frame *rtda.Frame) []*StackTraceElement { thread := frame.Thread() depth := thread.StackDepth() // skip unrelated frames i := uint(1) for k := tObj.Class(); k != nil; k = k.SuperClass() { i++ } if thread.TopFrameN(i).Method().Name() == "<athrow>" { i++ } stes := make([]*StackTraceElement, 0, depth) for ; i < depth; i++ { frameN := thread.TopFrameN(i) methodN := frameN.Method() classN := methodN.Class() if classN.Name() != "~shim" { // skip shim frame lineNumber := methodN.GetLineNumber(frameN.NextPC() - 1) ste := &StackTraceElement{ declaringClass: classN.NameJlsFormat(), methodName: methodN.Name(), fileName: classN.SourceFile(), lineNumber: lineNumber, } stes = append(stes, ste) } } return stes }
func (self *LRETURN) Execute(frame *rtda.Frame) { thread := frame.Thread() currentFrame := thread.PopFrame() invokerFrame := thread.TopFrame() val := currentFrame.OperandStack().PopLong() invokerFrame.OperandStack().PushLong(val) }
// private native void open(String name, int mode) throws FileNotFoundException; // (Ljava/lang/String;)V func raf_open(frame *rtda.Frame) { vars := frame.LocalVars() this := vars.GetThis() name := vars.GetRef(1) mode := vars.GetInt(2) //flag flag := 0 if mode&1 > 0 { flag |= os.O_RDONLY } //write if mode&2 > 0 { flag |= os.O_RDWR | os.O_CREATE } if mode&4 > 0 { flag |= os.O_SYNC | os.O_CREATE } if mode&8 > 0 { //TODO:O_DSYNC flag |= os.O_SYNC | os.O_CREATE } goName := rtda.GoString(name) if goFile, err := os.OpenFile(goName, flag, 0660); err != nil { frame.Thread().ThrowFileNotFoundException(goName) } else { this.SetExtra(goFile) } }
// public native void setLength(long newLength) throws IOException; // (J)V func raf_setLength(frame *rtda.Frame) { vars := frame.LocalVars() this := vars.GetThis() //length := vars.GetLong(1) goFile := this.Extra().(*os.File) cur, _ := goFile.Seek(0, os.SEEK_CUR) //TODO //How do set file length in Go ? panic("native method not implement! RandomAccessFile.setLength") var newLength int64 newLength = 0 if cur > newLength { if _, err := goFile.Seek(0, os.SEEK_END); err != nil { frame.Thread().ThrowIOException("setLength failed") } } else { if _, err := goFile.Seek(cur, os.SEEK_SET); err != nil { frame.Thread().ThrowIOException("setLength failed") } } }
func (self *ATHROW) Execute(frame *rtda.Frame) { ex := frame.OperandStack().PopRef() if ex == nil { frame.Thread().ThrowNPE() return } thread := frame.Thread() for { frame := thread.CurrentFrame() pc := frame.NextPC() - 1 handler := frame.Method().FindExceptionHandler(ex.Class(), pc) if handler != nil { stack := frame.OperandStack() stack.Clear() stack.PushRef(ex) frame.SetNextPC(handler.HandlerPc()) return } thread.PopFrame() if thread.IsStackEmpty() { break } } thread.HandleUncaughtException(ex) }
// native void socketConnect(InetAddress address, int port, int timeout) // throws IOException; func psi_socketConnect(frame *rtda.Frame) { vars := frame.LocalVars() this := vars.GetThis() address := vars.GetRef(1) port := vars.Get(2) holder := address.GetFieldValue("holder", "Ljava/net/InetAddress$InetAddressHolder;").(*rtc.Obj) //fmt.Println(address.Class().GetInstanceMethod("getHostAddress", "()Ljava/lang/String;").NativeMethod()) add := holder.GetFieldValue("address", "I").(int32) b := make([]byte, 4) binary.BigEndian.PutUint32(b, uint32(add)) laddr := fmt.Sprintf("%d.%d.%d.%d:%d", b[0], b[1], b[2], b[3], port) conn, err := net.Dial("tcp", laddr) if err != nil { frame.Thread().ThrowIOException(err.Error()) } //TODO what ? timeout how to implement ? _timeout := vars.GetInt(3) if _timeout > 0 { conn.SetDeadline(time.Now().Add(time.Duration(_timeout) * time.Millisecond)) } fdObj := this.GetFieldValue("fd", "Ljava/io/FileDescriptor;").(*rtc.Obj) fdObj.SetExtra(conn) }
func (self *ARETURN) Execute(frame *rtda.Frame) { thread := frame.Thread() currentFrame := thread.PopFrame() invokerFrame := thread.TopFrame() ref := currentFrame.OperandStack().PopRef() invokerFrame.OperandStack().PushRef(ref) }
// public static native Class<?> getCallerClass(int i); // (I)Ljava/lang/Class; func getCallerClass(frame *rtda.Frame) { // top0 is sun/reflect/Reflection // top1 is the caller of getCallerClass() // top2 is the caller of method callerFrame := frame.Thread().TopFrameN(2) callerClass := callerFrame.Method().Class().JClass() frame.OperandStack().PushRef(callerClass) }
// private native void close0() throws IOException; // ()V func raf_close0(frame *rtda.Frame) { vars := frame.LocalVars() this := vars.GetThis() goFile := this.Extra().(*os.File) if err := goFile.Close(); err != nil { frame.Thread().ThrowIOException(err.Error()) } }
// @CallerSensitive // public static native <T> T doPrivileged(PrivilegedAction<T> action); // (Ljava/security/PrivilegedAction;)Ljava/lang/Object; func doPrivileged(frame *rtda.Frame) { vars := frame.LocalVars() action := vars.GetRef(0) stack := frame.OperandStack() stack.PushRef(action) method := action.Class().GetInstanceMethod("run", "()Ljava/lang/Object;") // todo frame.Thread().InvokeMethod(method) }
func (self *MONITOR_EXIT) Execute(frame *rtda.Frame) { thread := frame.Thread() ref := frame.OperandStack().PopRef() if ref == nil { frame.RevertNextPC() thread.ThrowNPE() } else { ref.Monitor().Exit(thread) } }
func (self *NEW_ARRAY) Execute(frame *rtda.Frame) { stack := frame.OperandStack() count := stack.PopInt() if count < 0 { frame.Thread().ThrowNegativeArraySizeException() return } arr := heap.NewPrimitiveArray(self.atype, uint(count)) stack.PushRef(arr) }
func _checkArrayAndIndex(frame *rtda.Frame, arrRef *rtc.Obj, index int32) bool { if arrRef == nil { frame.Thread().ThrowNPE() return false } if index < 0 || index >= rtc.ArrayLength(arrRef) { frame.Thread().ThrowArrayIndexOutOfBoundsException(index) return false } return true }
func (self *INVOKE_SPECIAL) Execute(frame *rtda.Frame) { cp := frame.Method().Class().ConstantPool() k := cp.GetConstant(self.Index) if kMethodRef, ok := k.(*heap.ConstantMethodref); ok { method := kMethodRef.SpecialMethod() frame.Thread().InvokeMethod(method) } else { method := k.(*heap.ConstantInterfaceMethodref).SpecialMethod() frame.Thread().InvokeMethod(method) } }
func _callValueOf(frame *rtda.Frame, primitiveDescriptor, wrapperClassName string) { wrapperClass := rtc.BootLoader().LoadClass(wrapperClassName) valueOfDescriptor := "(" + primitiveDescriptor + ")L" + wrapperClassName + ";" valueOfMethod := wrapperClass.GetStaticMethod("valueOf", valueOfDescriptor) frame.Thread().InvokeMethod(valueOfMethod) // init wrapper class if wrapperClass.InitializationNotStarted() { frame.Thread().InitClass(wrapperClass) } }
func (self *IREM) Execute(frame *rtda.Frame) { stack := frame.OperandStack() v2 := stack.PopInt() v1 := stack.PopInt() if v2 == 0 { frame.Thread().ThrowDivByZero() } else { result := v1 % v2 stack.PushInt(result) } }
// private native void write0(int b) throws IOException; // (I)V func raf_write0(frame *rtda.Frame) { vars := frame.LocalVars() this := vars.GetThis() intObj := vars.GetInt(1) // b goFile := this.Extra().(*os.File) //b := make([]byte, 4) //binary.BigEndian.PutUint32(b, uint32(intObj)) if _, err := goFile.Write([]byte{byte(intObj)}); err != nil { frame.Thread().ThrowIOException(err.Error()) } }
func (self *ARRAY_LENGTH) Execute(frame *rtda.Frame) { stack := frame.OperandStack() arrRef := stack.PopRef() if arrRef == nil { frame.Thread().ThrowNPE() return } arrLen := rtc.ArrayLength(arrRef) stack.PushInt(arrLen) }
func (self *LDIV) Execute(frame *rtda.Frame) { stack := frame.OperandStack() v2 := stack.PopLong() v1 := stack.PopLong() if v2 == 0 { frame.Thread().ThrowDivByZero() } else { result := v1 / v2 stack.PushLong(result) } }
// public native void ensureClassInitialized(Class<?> c); // (Ljava/lang/Class;)V func ensureClassInitialized(frame *rtda.Frame) { vars := frame.LocalVars() // this := vars.GetRef(0) classObj := vars.GetRef(1) goClass := classObj.Extra().(*rtc.Class) if goClass.InitializationNotStarted() { // undo ensureClassInitialized() frame.RevertNextPC() // init frame.Thread().InitClass(goClass) } }
// private static native Class<?> defineClass0(ClassLoader loader, String name, // byte[] b, int off, int len); // (Ljava/lang/ClassLoader;Ljava/lang/String;[BII)Ljava/lang/Class; func defineClass0(frame *rtda.Frame) { stack := frame.OperandStack() if stack.IsEmpty() { _loadClass(frame) } // init class class := stack.TopRef(0).Extra().(*heap.Class) if class.InitializationNotStarted() { frame.RevertNextPC() frame.Thread().InitClass(class) } }
// public final native void notifyAll(); // ()V func notifyAll(frame *rtda.Frame) { vars := frame.LocalVars() this := vars.GetThis() thread := frame.Thread() monitor := this.Monitor() if !monitor.HasOwner(thread) { // todo panic("IllegalMonitorStateException") } monitor.NotifyAll() }
// public native long getFilePointer() throws IOException; // ()J func raf_getFilePointer(frame *rtda.Frame) { vars := frame.LocalVars() this := vars.GetThis() goFile := this.Extra().(*os.File) if pos, err := goFile.Seek(0, os.SEEK_CUR); err != nil { frame.Thread().ThrowIOException("Seek failed") } else { frame.OperandStack().PushLong(pos) } }
// native ConstantPool getConstantPool(); // ()Lsun/reflect/ConstantPool; func getConstantPool(frame *rtda.Frame) { class := _popClass(frame) cpClass := rtc.BootLoader().LoadClass("sun/reflect/ConstantPool") if cpClass.InitializationNotStarted() { frame.RevertNextPC() frame.Thread().InitClass(cpClass) return } cp := class.ConstantPool() cpObj := cpClass.NewObjWithExtra(cp) // todo init cpObj frame.OperandStack().PushRef(cpObj) }
// native void socketAccept(SocketImpl s) func psi_socketAccept(frame *rtda.Frame) { vars := frame.LocalVars() this := vars.GetThis() s := vars.GetRef(1) fdObj := s.GetFieldValue("fd", "Ljava/io/FileDescriptor;").(*rtc.Obj) //goFd := fdObj.GetFieldValue("fd", "I").(int32) listen := this.Extra().(net.Listener) if conn, err := listen.Accept(); err != nil { frame.Thread().ThrowIOException(err.Error()) } else { fdObj.SetExtra(conn) } }
// public final native void wait(long timeout) throws InterruptedException; // (J)V func wait(frame *rtda.Frame) { vars := frame.LocalVars() this := vars.GetThis() // timeout := vars.GetLong(1) // todo thread := frame.Thread() monitor := this.Monitor() if !monitor.HasOwner(thread) { // todo panic("IllegalMonitorStateException") } monitor.Wait() }
// native ClassLoader getClassLoader0(); // ()Ljava/lang/ClassLoader; func getClassLoader0(frame *rtda.Frame) { class := _popClass(frame) from := class.LoadedFrom() stack := frame.OperandStack() if cp.IsBootClassPath(from) { stack.PushRef(nil) return } clClass := rtc.BootLoader().LoadClass("java/lang/ClassLoader") getSysCl := clClass.GetStaticMethod("getSystemClassLoader", "()Ljava/lang/ClassLoader;") frame.Thread().InvokeMethod(getSysCl) }
// public native ByteBuffer createLong(String name, int variability, int units, long value); // (Ljava/lang/String;IIJ)Ljava/nio/ByteBuffer; func createLong(frame *rtda.Frame) { bbClass := frame.ClassLoader().LoadClass("java/nio/ByteBuffer") if bbClass.InitializationNotStarted() { frame.RevertNextPC() frame.Thread().InitClass(bbClass) return } stack := frame.OperandStack() stack.PushInt(8) allocate := bbClass.GetStaticMethod("allocate", "(I)Ljava/nio/ByteBuffer;") frame.Thread().InvokeMethod(allocate) }
// public static native void set(Object array, int index, Object value) // throws IllegalArgumentException, ArrayIndexOutOfBoundsException; // (Ljava/lang/Object;ILjava/lang/Object;)V func set(frame *rtda.Frame) { vars := frame.LocalVars() arr := vars.GetRef(0) index := vars.GetInt(1) value := vars.GetRef(2) if arr == nil { frame.Thread().ThrowNPE() return } if !arr.IsArray() { frame.Thread().ThrowIllegalArgumentException("Argument is not an array") return } if index < 0 || index >= heap.ArrayLength(arr) { frame.Thread().ThrowArrayIndexOutOfBoundsExceptionNoMsg() return } if !arr.IsPrimitiveArray() { arr.Refs()[index] = value return } //TODO Consistent with the current need to determine whether the type and source type // Such as: // [I // java/lang/Integer // frame.Thread().ThrowIllegalArgumentException("argument type mismatch") // primitive array primitiveDescriptorStr := arr.Class().Name()[1:] if primitiveDescriptorStr != value.GetPrimitiveDescriptor() { frame.Thread().ThrowIllegalArgumentException("argument type mismatch") return } unboxed := box.Unbox(value, primitiveDescriptorStr) primitiveDescriptor := arr.Class().Name()[1] switch primitiveDescriptor { case 'Z': arr.Booleans()[index] = int8(unboxed.(int32)) case 'B': arr.Bytes()[index] = int8(unboxed.(int32)) case 'C': arr.Chars()[index] = uint16(unboxed.(int32)) case 'S': arr.Shorts()[index] = int16(unboxed.(int32)) case 'I': arr.Ints()[index] = unboxed.(int32) case 'J': arr.Longs()[index] = unboxed.(int64) case 'F': arr.Floats()[index] = unboxed.(float32) case 'D': arr.Doubles()[index] = unboxed.(float64) } }
func (self *MULTI_ANEW_ARRAY) Execute(frame *rtda.Frame) { cp := frame.ConstantPool() kClass := cp.GetConstant(uint(self.index)).(*heap.ConstantClass) arrClass := kClass.Class() stack := frame.OperandStack() counts := stack.PopTops(uint(self.dimensions)) if !_checkCounts(counts) { frame.Thread().ThrowNegativeArraySizeException() } else { arr := _newMultiArray(counts, arrClass) stack.PushRef(arr) } }