예제 #1
0
 public Frame getLastFramePD(JavaThread thread, Address addr) {
   Address fp = thread.getLastJavaFP();
   if (fp == null) {
     return null; // no information
   }
   return new X86Frame(thread.getLastJavaSP(), fp);
 }
예제 #2
0
 // Get list of Java threads that have called Object.wait on the specified monitor.
 public List getWaitingThreads(ObjectMonitor monitor) {
   List pendingThreads = new ArrayList();
   for (JavaThread thread = first(); thread != null; thread = thread.next()) {
     ObjectMonitor waiting = thread.getCurrentWaitingMonitor();
     if (monitor.equals(waiting)) {
       pendingThreads.add(thread);
     }
   }
   return pendingThreads;
 }
예제 #3
0
 // refer to Threads::get_pending_threads
 // Get list of Java threads that are waiting to enter the specified monitor.
 public List getPendingThreads(ObjectMonitor monitor) {
   List pendingThreads = new ArrayList();
   for (JavaThread thread = first(); thread != null; thread = thread.next()) {
     if (thread.isCompilerThread() || thread.isCodeCacheSweeperThread()) {
       continue;
     }
     ObjectMonitor pending = thread.getCurrentPendingMonitor();
     if (monitor.equals(pending)) {
       pendingThreads.add(thread);
     }
   }
   return pendingThreads;
 }
예제 #4
0
 /**
  * Routine for instantiating appropriately-typed wrapper for a JavaThread. Currently needs to be
  * public for OopUtilities to access it.
  */
 public JavaThread createJavaThreadWrapper(Address threadAddr) {
   try {
     JavaThread thread = (JavaThread) virtualConstructor.instantiateWrapperFor(threadAddr);
     thread.setThreadPDAccess(access);
     return thread;
   } catch (Exception e) {
     throw new RuntimeException(
         "Unable to deduce type of thread from address "
             + threadAddr
             + " (expected type JavaThread, CompilerThread, ServiceThread, JvmtiAgentThread or CodeCacheSweeperThread)",
         e);
   }
 }
예제 #5
0
  // refer to Threads::owning_thread_from_monitor_owner
  public JavaThread owningThreadFromMonitor(Address o) {
    if (o == null) return null;
    for (JavaThread thread = first(); thread != null; thread = thread.next()) {
      if (o.equals(thread.threadObjectAddress())) {
        return thread;
      }
    }

    for (JavaThread thread = first(); thread != null; thread = thread.next()) {
      if (thread.isLockOwned(o)) return thread;
    }
    return null;
  }
  /** Runs the analysis algorithm */
  public void run() {
    if (VM.getVM().getRevPtrs() != null) {
      return; // Assume already done
    }

    VM vm = VM.getVM();
    rp = new ReversePtrs();
    vm.setRevPtrs(rp);
    Universe universe = vm.getUniverse();
    CollectedHeap collHeap = universe.heap();
    usedSize = collHeap.used();
    visitedSize = 0;

    // Note that an experiment to iterate the heap linearly rather
    // than in recursive-descent order has been done. It turns out
    // that the recursive-descent algorithm is nearly twice as fast
    // due to the fact that it scans only live objects and (currently)
    // only a fraction of the perm gen, namely the static fields
    // contained in instanceKlasses. (Iterating the heap linearly
    // would also change the semantics of the result so that
    // ReversePtrs.get() would return a non-null value even for dead
    // objects.) Nonetheless, the reverse pointer computation is still
    // quite slow and optimization in field iteration of objects
    // should be done.

    if (progressThunk != null) {
      // Get it started
      progressThunk.heapIterationFractionUpdate(0);
    }

    // Allocate mark bits for heap
    markBits = new MarkBits(collHeap);

    // Get a hold of the object heap
    heap = vm.getObjectHeap();

    // Do each thread's roots
    for (JavaThread thread = VM.getVM().getThreads().first();
        thread != null;
        thread = thread.next()) {
      ByteArrayOutputStream bos = new ByteArrayOutputStream();
      thread.printThreadIDOn(new PrintStream(bos));
      String threadDesc =
          " in thread \"" + thread.getThreadName() + "\" (id " + bos.toString() + ")";
      doStack(thread, new RootVisitor("Stack root" + threadDesc));
      doJNIHandleBlock(thread.activeHandles(), new RootVisitor("JNI handle root" + threadDesc));
    }

    // Do global JNI handles
    JNIHandles handles = VM.getVM().getJNIHandles();
    doJNIHandleBlock(handles.globalHandles(), new RootVisitor("Global JNI handle root"));
    doJNIHandleBlock(handles.weakGlobalHandles(), new RootVisitor("Weak global JNI handle root"));

    // Do Java-level static fields
    SystemDictionary sysDict = VM.getVM().getSystemDictionary();
    sysDict.allClassesDo(
        new SystemDictionary.ClassVisitor() {

          public void visit(Klass k) {
            if (k instanceof InstanceKlass) {
              final InstanceKlass ik = (InstanceKlass) k;
              ik.iterateStaticFields(
                  new DefaultOopVisitor() {
                    public void doOop(OopField field, boolean isVMField) {
                      Oop next = field.getValue(getObj());
                      NamedFieldIdentifier nfi =
                          new NamedFieldIdentifier(
                              "Static field \""
                                  + field.getID().getName()
                                  + "\" in class \""
                                  + ik.getName().asString()
                                  + "\"");
                      LivenessPathElement lp = new LivenessPathElement(null, nfi);
                      rp.put(lp, next);
                      try {
                        markAndTraverse(next);
                      } catch (AddressException e) {
                        System.err.print(
                            "RevPtrs analysis: WARNING: AddressException at 0x"
                                + Long.toHexString(e.getAddress())
                                + " while traversing static fields of InstanceKlass ");
                        ik.printValueOn(System.err);
                        System.err.println();
                      } catch (UnknownOopException e) {
                        System.err.println(
                            "RevPtrs analysis: WARNING: UnknownOopException while "
                                + "traversing static fields of InstanceKlass ");
                        ik.printValueOn(System.err);
                        System.err.println();
                      }
                    }
                  });
            }
          }
        });

    if (progressThunk != null) {
      progressThunk.heapIterationComplete();
    }

    // Clear out markBits
    markBits = null;
  }
  /** Returns false if not able to find a frame within a reasonable range. */
  public boolean run(long regionInBytesToSearch) {
    Address sp = context.getRegisterAsAddress(AMD64ThreadContext.RSP);
    Address pc = context.getRegisterAsAddress(AMD64ThreadContext.RIP);
    Address fp = context.getRegisterAsAddress(AMD64ThreadContext.RBP);
    if (sp == null) {
      // Bail out if no last java frame either
      if (thread.getLastJavaSP() != null) {
        setValues(thread.getLastJavaSP(), thread.getLastJavaFP(), null);
        return true;
      }
      return false;
    }
    Address end = sp.addOffsetTo(regionInBytesToSearch);
    VM vm = VM.getVM();

    setValues(null, null, null); // Assume we're not going to find anything

    if (vm.isJavaPCDbg(pc)) {
      if (vm.isClientCompiler()) {
        // If the topmost frame is a Java frame, we are (pretty much)
        // guaranteed to have a viable EBP. We should be more robust
        // than this (we have the potential for losing entire threads'
        // stack traces) but need to see how much work we really have
        // to do here. Searching the stack for an (SP, FP) pair is
        // hard since it's easy to misinterpret inter-frame stack
        // pointers as base-of-frame pointers; we also don't know the
        // sizes of C1 frames (not registered in the nmethod) so can't
        // derive them from ESP.

        setValues(sp, fp, pc);
        return true;
      } else {
        if (vm.getInterpreter().contains(pc)) {
          if (DEBUG) {
            System.out.println(
                "CurrentFrameGuess: choosing interpreter frame: sp = "
                    + sp
                    + ", fp = "
                    + fp
                    + ", pc = "
                    + pc);
          }
          setValues(sp, fp, pc);
          return true;
        }

        // For the server compiler, EBP is not guaranteed to be valid
        // for compiled code. In addition, an earlier attempt at a
        // non-searching algorithm (see below) failed because the
        // stack pointer from the thread context was pointing
        // (considerably) beyond the ostensible end of the stack, into
        // garbage; walking from the topmost frame back caused a crash.
        //
        // This algorithm takes the current PC as a given and tries to
        // find the correct corresponding SP by walking up the stack
        // and repeatedly performing stackwalks (very inefficient).
        //
        // FIXME: there is something wrong with stackwalking across
        // adapter frames...this is likely to be the root cause of the
        // failure with the simpler algorithm below.

        for (long offset = 0; offset < regionInBytesToSearch; offset += vm.getAddressSize()) {
          try {
            Address curSP = sp.addOffsetTo(offset);
            Frame frame = new X86Frame(curSP, null, pc);
            RegisterMap map = thread.newRegisterMap(false);
            while (frame != null) {
              if (frame.isEntryFrame() && frame.entryFrameIsFirst()) {
                // We were able to traverse all the way to the
                // bottommost Java frame.
                // This sp looks good. Keep it.
                if (DEBUG) {
                  System.out.println("CurrentFrameGuess: Choosing sp = " + curSP + ", pc = " + pc);
                }
                setValues(curSP, null, pc);
                return true;
              }
              frame = frame.sender(map);
            }
          } catch (Exception e) {
            if (DEBUG) {
              System.out.println("CurrentFrameGuess: Exception " + e + " at offset " + offset);
            }
            // Bad SP. Try another.
          }
        }

        // Were not able to find a plausible SP to go with this PC.
        // Bail out.
        return false;

        /*
        // Original algorithm which does not work because SP was
        // pointing beyond where it should have:

        // For the server compiler, EBP is not guaranteed to be valid
        // for compiled code. We see whether the PC is in the
        // interpreter and take care of that, otherwise we run code
        // (unfortunately) duplicated from AMD64Frame.senderForCompiledFrame.

        CodeCache cc = vm.getCodeCache();
        if (cc.contains(pc)) {
          CodeBlob cb = cc.findBlob(pc);

          // See if we can derive a frame pointer from SP and PC
          // NOTE: This is the code duplicated from AMD64Frame
          Address saved_fp = null;
          int llink_offset = cb.getLinkOffset();
          if (llink_offset >= 0) {
            // Restore base-pointer, since next frame might be an interpreter frame.
            Address fp_addr = sp.addOffsetTo(VM.getVM().getAddressSize() * llink_offset);
            saved_fp = fp_addr.getAddressAt(0);
          }

          setValues(sp, saved_fp, pc);
          return true;
        }
        */
      }
    } else {
      // If the current program counter was not known to us as a Java
      // PC, we currently assume that we are in the run-time system
      // and attempt to look to thread-local storage for saved ESP and
      // EBP. Note that if these are null (because we were, in fact,
      // in Java code, i.e., vtable stubs or similar, and the SA
      // didn't have enough insight into the target VM to understand
      // that) then we are going to lose the entire stack trace for
      // the thread, which is sub-optimal. FIXME.

      if (DEBUG) {
        System.out.println(
            "CurrentFrameGuess: choosing last Java frame: sp = "
                + thread.getLastJavaSP()
                + ", fp = "
                + thread.getLastJavaFP());
      }
      if (thread.getLastJavaSP() == null) {
        return false; // No known Java frames on stack
      }
      setValues(thread.getLastJavaSP(), thread.getLastJavaFP(), null);
      return true;
    }
  }
예제 #8
0
 /** Memory operations */
 public void oopsDo(AddressVisitor oopVisitor) {
   // FIXME: add more of VM functionality
   for (JavaThread thread = first(); thread != null; thread = thread.next()) {
     thread.oopsDo(oopVisitor);
   }
 }