defaultheapmanager.java
来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 349 行
JAVA
349 行
/**
* $Id: DefaultHeapManager.java,v 1.8 2004/02/24 09:03:29 epr Exp $
*/
package org.jnode.vm.memmgr.def;
import java.io.PrintStream;
import org.jnode.vm.Address;
import org.jnode.vm.MemoryBlockManager;
import org.jnode.vm.Monitor;
import org.jnode.vm.Unsafe;
import org.jnode.vm.VmArchitecture;
import org.jnode.vm.classmgr.ObjectFlags;
import org.jnode.vm.classmgr.ObjectLayout;
import org.jnode.vm.classmgr.VmClassLoader;
import org.jnode.vm.classmgr.VmClassType;
import org.jnode.vm.classmgr.VmNormalClass;
import org.jnode.vm.classmgr.VmStatics;
import org.jnode.vm.memmgr.HeapHelper;
import org.jnode.vm.memmgr.VmHeapManager;
import org.jnode.vm.memmgr.VmWriteBarrier;
public final class DefaultHeapManager extends VmHeapManager {
/** Default size in bytes of a new heap */
public static final int DEFAULT_HEAP_SIZE = 2 * 1024 * 1024;
/** When this percentage of the free memory has been allocated, a GC is triggered (0..1.0) */
public static float GC_TRIGGER_PERCENTAGE = 0.75f;
/** The GC thread */
private GCThread gcThread;
/** The finalizer thread */
private FinalizerThread finalizerThread;
/** Monitor to synchronize heap access */
private Monitor heapMonitor;
/** Are we low on memory */
private boolean lowOnMemory;
/** The used write barrier */
private final VmWriteBarrier writeBarrier;
/** The first heap. */
private final VmAbstractHeap firstHeap;
/** The heap currently used for allocation */
private VmAbstractHeap currentHeap;
/** The class of the default heap type. Set by initialize */
private final VmNormalClass defaultHeapClass;
private final VmStatics statics;
/** The number of allocated bytes since the last GC trigger */
private int allocatedSinceGcTrigger;
private int triggerSize = Integer.MAX_VALUE;
private boolean gcActive;
/**
* Make this private, so we cannot be instantiated
*/
public DefaultHeapManager(VmClassLoader loader, HeapHelper helper, VmStatics statics)
throws ClassNotFoundException {
super(helper);
//this.writeBarrier = new DefaultWriteBarrier(helper);
this.writeBarrier = null;
this.firstHeap = new VmDefaultHeap(this);
this.currentHeap = firstHeap;
this.defaultHeapClass = (VmNormalClass)loader.loadClass(VmDefaultHeap.class.getName(), true);
this.statics = statics;
}
/**
* Is the given address the address of an allocated object on this heap?
*
* @param ptr
* The address to examine.
* @return True if the given address if a valid starting address of an object, false otherwise.
*/
public final boolean isObject(Address ptr) {
long addrL = helper.addressToLong(ptr);
if ((addrL & (ObjectLayout.OBJECT_ALIGN - 1)) != 0) {
// The object is not at an object aligned boundary
return false;
}
if (bootHeap.isObject(ptr)) {
return true;
}
VmAbstractHeap heap = firstHeap;
while (heap != null) {
if (heap.isObject(ptr)) {
return true;
}
heap = heap.getNext();
}
return false;
}
/**
* Is the system low on memory?
* @return boolean
*/
public boolean isLowOnMemory() {
return lowOnMemory;
}
/**
* Start a garbage collection process
*/
public final void gc() {
gcThread.trigger(false);
}
/**
* Gets the size of free memory in bytes.
* @return long
*/
public long getFreeMemory() {
long size = bootHeap.getFreeSize();
VmAbstractHeap h = firstHeap;
while (h != null) {
size += h.getFreeSize();
h = h.getNext();
}
//size += (Unsafe.addressToLong(heapEnd) - Unsafe.addressToLong(nextHeapPtr));
size += MemoryBlockManager.getFreeMemory();
return size;
}
/**
* Gets the size of all memory in bytes.
*
* @return the size of all memory in bytes
*/
public long getTotalMemory() {
long size = bootHeap.getSize();
VmAbstractHeap h = firstHeap;
while (h != null) {
size += h.getSize();
h = h.getNext();
}
//size += (Unsafe.addressToLong(heapEnd) - Unsafe.addressToLong(nextHeapPtr));
size += MemoryBlockManager.getFreeMemory();
return size;
}
/**
* Gets the first heap. All other heaps can be iterated through the <code>getNext()</code>
* method.
*
* @return the first heap
*/
public final VmAbstractHeap getFirstHeap() {
return firstHeap;
}
// ------------------------------------------
// Private natives
// ------------------------------------------
protected void initialize() {
// Set the basic fields
final VmArchitecture arch = Unsafe.getCurrentProcessor().getArchitecture();
final int slotSize = arch.getReferenceSize();
// Initialize the boot heap.
bootHeap.initialize(helper.getBootHeapStart(), helper.getBootHeapEnd(), slotSize);
// Initialize the first normal heap
Address ptr = helper.allocateBlock(DEFAULT_HEAP_SIZE);
firstHeap.initialize(ptr, Address.add(ptr, DEFAULT_HEAP_SIZE), slotSize);
}
public void start() {
// Create a Heap monitor
heapMonitor = new Monitor();
final VmArchitecture arch = Unsafe.getCurrentProcessor().getArchitecture();
final GCManager gcManager = new GCManager(this, arch, statics);
this.gcThread = new GCThread(gcManager, heapMonitor);
this.finalizerThread = new FinalizerThread(this);
gcThread.start();
finalizerThread.start();
// Calculate the trigger size
triggerSize = (int)Math.min(Integer.MAX_VALUE, getFreeMemory() * GC_TRIGGER_PERCENTAGE);
}
/**
* Gets the write barrier used by this heap manager (if any).
* @return The write barrier, or null if no write barrier is used.
*/
public final VmWriteBarrier getWriteBarrier() {
return writeBarrier;
}
/**
* Allocate a new instance for the given class. Not that this method cannot be synchronized,
* since obtaining a monitor might require creating one, which in turn needs this method.
*
* @param vmClass
* @param size
* @return Object
*/
protected Object allocObject(VmClassType vmClass, int size) {
if (size > DEFAULT_HEAP_SIZE) {
throw new OutOfMemoryError("Object too large (" + size + ")");
}
if (gcActive) {
Unsafe.debug("allocObject(");
Unsafe.debug(vmClass.getName());
Unsafe.debug(", ");
Unsafe.debug(size);
Unsafe.debug(");");
Unsafe.getCurrentProcessor().getArchitecture().getStackReader()
.debugStackTrace();
helper.die("allocObject during GC");
}
// Make sure the class is initialized
vmClass.initialize();
final int alignedSize = ObjectLayout.objectAlign(size);
//final Monitor mon = heapMonitor;
VmAbstractHeap heap = currentHeap;
Object result = null;
int oomCount = 0;
final Monitor m = heapMonitor;
//final Monitor m = null;
if (m != null) {
m.enter();
}
try {
while (result == null) {
// The current heap is full
if (heap == null) {
//Unsafe.debug("allocHeap in allocObject("); Unsafe.debug(alignedSize);
//Unsafe.debug(") ");
if ((heap = allocHeap(DEFAULT_HEAP_SIZE)) == null) {
lowOnMemory = true;
// It was not possible to allocate another heap.
// First try to GC, if we've done that before
// in this allocation, then we're in real panic.
if (oomCount == 0) {
oomCount++;
Unsafe.debug("<oom/>");
gcThread.trigger(true);
heap = firstHeap;
currentHeap = firstHeap;
} else {
Unsafe.debug("Out of memory in allocObject(");
Unsafe.debug(size);
Unsafe.debug(")");
throw OOME;
//Unsafe.die();
}
} else {
//Unsafe.debug("AO.G");
// We successfully allocated a new heap, set it
// to current, so we'll use it for the following
// allocations.
currentHeap = heap;
}
}
result = heap.alloc(vmClass, alignedSize);
if (result == null) {
heap = heap.getNext();
}
}
vmClass.incInstanceCount();
lowOnMemory = false;
// Allocated objects are initially black.
helper.unsafeSetObjectFlags(result, ObjectFlags.GC_DEFAULT_COLOR);
allocatedSinceGcTrigger += alignedSize;
if ((allocatedSinceGcTrigger > triggerSize) && (gcThread != null)) {
Unsafe.debug("<alloc:GC trigger/>");
allocatedSinceGcTrigger = 0;
gcThread.trigger(false);
}
} finally {
if (m != null) {
m.exit();
}
}
return result;
}
/**
* Allocate a new heap with a given size. The heap object itself is allocated on the new heap,
* so this method can be called even if all other heaps are full.
*
* @param size
* @return The heap
*/
private VmAbstractHeap allocHeap(int size) {
//Unsafe.debug("allocHeap");
final Address start = helper.allocateBlock(size);
//final Address start = MemoryBlockManager.allocateBlock(size);
if (start == null) {
return null;
}
final Address end = Address.add(start, size);
final int slotSize = Unsafe.getCurrentProcessor().getArchitecture().getReferenceSize();
final VmAbstractHeap heap = VmDefaultHeap.setupHeap(helper, start, defaultHeapClass, slotSize);
heap.initialize(start, end, slotSize);
firstHeap.append(heap);
return heap;
}
/**
* Print the statics on this object on out.
*/
public void dumpStatistics(PrintStream out) {
out.println("WriteBarrier: " + writeBarrier);
}
/**
* @return Returns the bootHeap.
*/
final VmBootHeap getBootHeap() {
return this.bootHeap;
}
/**
* @param gcActive The gcActive to set.
*/
final void setGcActive(boolean gcActive) {
this.gcActive = gcActive;
}
/**
* Sets the currentHeap to the first heap.
*/
final void resetCurrentHeap() {
this.currentHeap = this.firstHeap;
// Recalculate the trigger size
triggerSize = (int)Math.min(Integer.MAX_VALUE, getFreeMemory() * GC_TRIGGER_PERCENTAGE);
}
/**
* Sets the currentHeap to the first heap.
*/
final void triggerFinalization() {
finalizerThread.trigger(false);
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?