提到Java语言的特点,无论是教科书还是程序员一般都会罗列出面向对象、可移植性及安全等特点。但如果你是一位刚从C/C++转到Java的程序员,对Java语言的特性除了面向对象之外,最外直接的应当是在Java虚拟机(JVM)在内存管理方面给我们变成带来的便利。JVM的这一大特性使Java程序员从繁琐的内存管理工作中得到了一定解放,但是JVM的这个特点的实现也是有代价的,并且它也并非万能。因此如果一个编程习惯不好的Java程序员如果完全将内存回收寄希望于JVM,那么OOM(Out Of Memory)就已经悄悄潜伏在了他的程序之中。
void ensureGone(KeyedWeakReference reference, long watchStartNanoTime) { ...
removeWeaklyReachableReferences(); if (gone(reference) || debuggerControl.isDebuggerAttached()) { return; } gcTrigger.runGc(); // 手动执行一次gc removeWeaklyReachableReferences(); if (!gone(reference)) {
long startDumpHeap = System.nanoTime(); long gcDurationMs = NANOSECONDS.toMillis(startDumpHeap - gcStartNanoTime);
File heapDumpFile = heapDumper.dumpHeap(); if (heapDumpFile == null) { // Could not dump the heap, abort. Log.d(TAG, "Could not dump the heap, abort."); return; } long heapDumpDurationMs = NANOSECONDS.toMillis(System.nanoTime() - startDumpHeap);
// False alarm, weak reference was cleared in between key check and heap dump. if (leakingRef == null) { return noLeak(since(analysisStartNanoTime)); }
if (refClasses.size() != 1) { throw new IllegalStateException( "Expecting one class for " + KeyedWeakReference.class.getName() + " in " + refClasses); }
public int[] getNextShortestPath() throws SnapshotException { switch (state) { case 0: // INITIAL {
... } case 1: // FINAL return null;
case 2: // PROCESSING GC ROOT { ... } case 3: // NORMAL PROCESSING { int[] res;
// finish processing the current entry if (currentReferrers != null) { res = processCurrentReferrefs(lastReadReferrer + 1); if (res != null) return res; }
// Continue with the FIFO while (fifo.size() > 0) { currentPath = fifo.getFirst(); fifo.removeFirst(); currentId = currentPath.getIndex(); currentReferrers = inboundIndex.get(currentId);
if (currentReferrers != null) { res = processCurrentReferrefs(0); if (res != null) return res; } } return null; }
default: ... } }
private int[] processCurrentReferrefs(int fromIndex) throws SnapshotException { GCRootInfo[] rootInfo = null; for (int i = fromIndex; i < currentReferrers.length; i++) { ... } for (int referrer : currentReferrers) { if (referrer >= 0 && !visited.get(referrer) && !roots.containsKey(referrer)) { if (excludeMap == null) { fifo.add(new Path(referrer, currentPath)); visited.set(referrer); } else { if (!refersOnlyThroughExcluded(referrer, currentId)) { fifo.add(new Path(referrer, currentPath)); visited.set(referrer); } } } } return null; } }