-
Notifications
You must be signed in to change notification settings - Fork 46.1k
Closed
Labels
doc-bugContent errorContent error
Description
在docs/java/basis/unsafe.md中有如下描述:
如果你是一个写过 C 或者 C++ 的程序员,一定对内存操作不会陌生,而在 Java 中是不允许直接对内存进行操作的,对象内存的分配和回收都是由 JVM 自己实现的。但是在
Unsafe中,提供的下列接口可以直接进行内存操作://分配新的本地空间 public native long allocateMemory(long bytes); //重新调整内存空间的大小 public native long reallocateMemory(long address, long bytes); //将内存设置为指定值 public native void setMemory(Object o, long offset, long bytes, byte value); //内存拷贝 public native void copyMemory(Object srcBase, long srcOffset,Object destBase, long destOffset,long bytes); //清除内存 public native void freeMemory(long address);使用下面的代码进行测试:
private void memoryTest() { int size = 4; long addr = unsafe.allocateMemory(size); long addr3 = unsafe.reallocateMemory(addr, size * 2); System.out.println("addr: "+addr); System.out.println("addr3: "+addr3); try { unsafe.setMemory(null,addr ,size,(byte)1); for (int i = 0; i < 2; i++) { unsafe.copyMemory(null,addr,null,addr3+size*i,4); } System.out.println(unsafe.getInt(addr)); System.out.println(unsafe.getLong(addr3)); }finally { unsafe.freeMemory(addr); unsafe.freeMemory(addr3); } }先看结果输出:
addr: 2433733895744 addr3: 2433733894944 16843009 72340172838076673分析一下运行结果,首先使用
allocateMemory方法申请 4 字节长度的内存空间,调用setMemory方法向每个字节写入内容为byte类型的 1,当使用 Unsafe 调用getInt方法时,因为一个int型变量占 4 个字节,会一次性读取 4 个字节,组成一个int的值,对应的十进制结果为 16843009。
示例代码在调用reallocateMemory后,原地址addr其实已经释放,后续再对addr操作是不安全的,最后的unsafe.freeMemory(addr)更是会直接导致JVM崩溃。
Java中reallocateMemory的行为类似于C中的realloc,以下是百度百科中对realloc函数功能的描述:
先判断当前的指针是否有足够的连续空间,如果有,扩大mem_address指向的地址,并且将mem_address返回,如果空间不够,先按照newsize指定的大小分配空间,将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来mem_address所指内存区域(注意:原来指针是自动释放,不需要使用free),同时返回新分配的内存区域的首地址。即重新分配存储器块的地址。
ps.这里顺便表达一下对Guide哥的感谢,创作和整理这些优质的技术文章不容易,我从中收获很多,辛苦Guide哥👍
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
doc-bugContent errorContent error