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); }
/** 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(); } }
public void leave(ThreadInfo ti) { // <2do> - that's not really enough, we might have suspicious bytecode that fails // to release locks acquired by monitor_enter (e.g. by not having a handler that // monitor_exits & re-throws). That's probably shifted into the bytecode verifier // in the future (i.e. outside JPF), but maybe we should add an explicit test here // and report an error if the code does asymmetric locking (according to the specs, // VMs are allowed to silently fix this, so it might run on some and fail on others) if (isSynchronized()) { ElementInfo ei = getBlockedObject(ti, false); ei.unlock(ti); if (isStatic() && isClinit()) { // we just released the lock on the class object, returning from a clinit // now we can consider this class to be initialized. // NOTE this is still part of the RETURN insn of clinit, so ClassInfo.isInitialized // is protected ci.setInitialized(); } } ti.getVM().notifyMethodExited(ti, this); }