예제 #1
0
  public ElementInfo getBlockedObject(ThreadInfo th, boolean isBeforeCall) {
    int objref;
    ElementInfo ei = null;

    if (isSynchronized()) {
      if (isStatic()) {
        objref = ci.getClassObjectRef();
      } else {
        // NOTE 'inMethod' doesn't work for natives, because th.getThis()
        // pulls 'this' from the stack frame, which we don't have (and don't need)
        // for natives
        objref = isBeforeCall ? th.getCalleeThis(this) : th.getThis();
      }

      ei = th.getElementInfo(objref);

      assert (ei != null)
          : ("inconsistent stack, no object or class ref: "
              + getCompleteName()
              + " ("
              + objref
              + ")");
    }

    return ei;
  }
예제 #2
0
  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);
  }
예제 #3
0
  /** 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();
    }
  }
예제 #4
0
  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);
  }
예제 #5
0
 public boolean isThreadEntry(ThreadInfo ti) {
   return (uniqueName.equals("run()V") && (ti.countStackFrames() == 1));
 }