/** execute this method, which might be either bytecode or native. */ public Instruction execute(ThreadInfo ti) { if (((attrs & MJI_NATIVE) != 0) || isNative()) { NativePeer nativePeer = ci.getNativePeer(); if (nativePeer != null) { JVM vm = ti.getVM(); StackFrame frame = new StackFrame(this, ti.getTopFrame()); // since there is no enter/leave for native methods, we have to do // the notifications explicitly ti.pushFrame(frame); // Make the logic easier in listeners (e.g. vm.getLastMethod() == // vm.getCurrentThread().getMethod()) vm.notifyMethodEntered(ti, this); ti.popFrame( false); // Can't keep the frame for later in this method since nativePeer.executeMethod // will do work on the top of the stack // <2do> Allow for the frame to remain on the stack for the duration of the call to // nativePeer.executeMethod(). Instruction nextInsn = nativePeer.executeMethod(ti, this); ti.pushFrame(frame); // Make the logic easier in listeners (e.g. vm.getLastMethod() == // vm.getCurrentThread().getMethod()) vm.notifyMethodExited(ti, this); ti.popFrame(false); // Can't keep the frame since we don't want to leak frames. return nextInsn; } else { return ti.createAndThrowException( "java.lang.UnsatisfiedLinkError", ci.getName() + '.' + getUniqueName() + " (no peer)"); } } else { enter(ti); return ti.getPC(); } }
private void enter(ThreadInfo ti) { if (isSynchronized()) { ElementInfo ei = getBlockedObject(ti, true); ei.lock(ti); if (isStatic() && isClinit()) { ci.setInitializing(ti); } } StackFrame frame = new StackFrame(this, ti.getTopFrame()); ti.pushFrame(frame); ti.getVM().notifyMethodEntered(ti, this); }