标签:name har 区别 构造 == col round 回收 分析
问题
java 进程的内存占用到底是怎么样的呢?
我们都知道 jvm 有垃圾回收机制,并且回收的重点区域就是堆,假如我们以堆内堆外来区分内存区域,上图所示
以下描述代码图片来自 : https://blog.csdn.net/mycs2012/java/article/details/93513057 , 非原创
public static void main(String[] args) throws Exception {
// 分配
ByteBuffer buffer = ByteBuffer.allocateDirect(128);
// 写入
buffer.put("写入到直接内存".getBytes(Charset.forName("utf-8")));
// 读取
buffer.flip();
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
System.out.println(new String(bytes, Charset.forName("utf-8")));
System.gc(); // 不是必须
}
下面是 DirectByteBuffer 的构造方法
DirectByteBuffer(int cap) {
super(-1, 0, cap, cap);
boolean pa = VM.isDirectMemoryPageAligned(); // 获取是否开启内存页对齐选项
int ps = Bits.pageSize(); // 内存页大小
long size = Math.max(1L, (long)cap + (pa ? ps : 0)); // 计算size,后面按size进行实际内存占用
Bits.reserveMemory(size, cap); // 累加,控制直接内存的访问量
long base = 0;
try {
base = unsafe.allocateMemory(size);
} catch (OutOfMemoryError x) {
Bits.unreserveMemory(size, cap);
throw x;
}
unsafe.setMemory(base, size, (byte) 0);
if (pa && (base % ps != 0)) {
// Round up to page boundary
address = base + ps - (base & (ps - 1)); // 启用内存页对齐时
} else {
address = base; // 未启用内存页对齐时
}
cleaner = Cleaner.create(this, new Deallocator(base, size, cap));
att = null;
}
主要的操作有 : 1、通过unsafe.allocateMemory(size)分配一段大小为size的内存,这是个native方法,表明会通过JNI调用操作系统本地的系统调用接口。该方法最终会调用操作系统的malloc方法,进行内存的分配,分配成功后返回一个基地址,这个基地址最后转换为address,DirectByteBuffer对象就是通过address和size引用这段内存。
2、创建Cleaner对象,后续用于清理直接内存。
而这个 Cleaner 类是如何达到回收内存的效果的呢 , Cleaner 对象会持有Deallocator,在执行收集的时候调用其 run 方法
public class Cleaner extends PhantomReference<Object> {
....
}
Cleaner 是虚引用的之类,虚引用的容易被回收,当被回收就回调用 Cleaner 的 clean 方法
private static class Deallocator
implements Runnable
{
private static Unsafe unsafe = Unsafe.getUnsafe();
private long address;
private long size;
private int capacity;
private Deallocator(long address, long size, int capacity) {
assert (address != 0);
this.address = address;
this.size = size;
this.capacity = capacity;
}
public void run() {
if (address == 0) {
// Paranoia
return;
}
// 使用unsafe方法释放内存
unsafe.freeMemory(address);
address = 0;
// 更新统计变量
Bits.unreserveMemory(size, capacity);
}
}
jvm学习(一)DirectByteBuffer堆外内存浅析
标签:name har 区别 构造 == col round 回收 分析
原文地址:https://www.cnblogs.com/Benjious/p/13274438.html