当前位置:网站首页>Use of off heap memory
Use of off heap memory
2022-07-26 09:13:00 【Or turn around】
stay Jdk1.8 after ,jvm The memory model has been adjusted , That is, the implementation of the method area is from permanent generation (Perm Space) It becomes a meta space (MetaSpace). Metaspace is not in the virtual machine , Instead, it directly uses the system memory . For convenience , Hereinafter, virtual machine memory is called heap memory , Against it , Direct memory is called off heap memory .
Why use off heap memory
Before talking about why we should use off heap memory , We have to talk about heap memory . In heap memory is Java Virtual machine memory , Managed by virtual machines , Developers don't have to worry about the allocation and recycling of memory space . But there are advantages and disadvantages , The disadvantage of heap memory is :
- Garbage recycling has costs , The more objects in the heap ,GC The greater the cost .
- Use heap memory for file 、 Online IO when ,JVM Will use the off heap memory for an additional transfer , That is, one more memory copy .
And off heap memory directly uses machine memory , Managed by the operating system . To a certain extent, it reduces the impact of garbage collection on Applications .
Actual case
The blogger himself has never encountered the scene of having to use off heap memory in actual work . however 《 Ant message middleware (MsgBroker) stay YGC Exploration on Optimization 》 There is a relatively complete case in this article ( Reference material 2).
The business scenario in this article is the use of ant's message oriented middleware . To ensure the reliability of the message , Persisting messages to a database , In order to reduce the accuracy of message delivery db Reading pressure , The message is cached . In this way, the virtual machine will allocate memory for cached messages . When the message in the cache is not delivered successfully for various reasons , These news will be maintained all the time , And more and more . In heap space, objects change from young generation to old generation , It takes up more and more space . The final problem is that of the younger generation gc Time is too long ( exceed 100ms).
So here comes the question , Why does the increase of objects in old age lead to ygc The time is getting longer ? According to the answer in the text :
stay ygc Most of the time is older-gen scanning, This stage is mainly used to scan the references held by the elderly generation to the objects of the younger generation . In a scenario where messages are cached and a large number of messages cannot be delivered , A large number of young objects have been transformed into old objects , And holds references to younger generation objects . under these circumstances , The scanning time is relatively long .
The final solution is to use off heap memory , Reduce message pairs JVM Memory usage , And use the Netty Network layer framework , Achieved the ideal YGC Time .
Out of heap memory usage
Off heap memory can be used in two ways .
Unsafe Class action
sun.misc.Unsafe Provides a set of methods to allocate out of heap memory , Redistribute and release .
Unsafe yes java Back door for developers , It is used to directly operate the system memory and is not affected by jvm Have jurisdiction over , The implementation is similar to c++ Style operation . But generally, it is not recommended to use , As the class name shows , It's not safe , Easy to cause memory leaks .
Unsafe Most methods of class are native Method , Directly call methods in other languages ( For the most part c++) To operate , Many details cannot be traced , Can only roughly understand . Unsafe Class in jdk9 Then moved to jdk.unsupported Module .
- public native long allocateMemory(long size): Allocate memory space
- public native long reallocateMemory(long address, long size): Reallocate a piece of memory , The data from address Copy to the new memory block in the cache pointed to .
- public native void freeMemory(long address): Free memory
Unsafe The constructor of a class is private , Provides getUnsafe Method is used to get its instance . However, this method is not open to ordinary developers , Exceptions will be reported when using :java.lang.SecurityException: Unsafe. You can use this class through the reflection mechanism . As shown below :
public class unsafeDemo {
public static void main(String[] args) {
Unsafe unsafe = null;
long memoryAddress = 0;
try {
// obtain Unsafe Private singleton object of type
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
unsafe = (Unsafe) field.get(null);
memoryAddress = unsafe.allocateMemory(1024);
// take int Type integer is stored in the specified address
unsafe.putInt(memoryAddress, 5);
// Get an integer according to the address
int a = unsafe.getInt(memoryAddress);
System.out.println(a);
} catch (Exception e) {
e.printStackTrace();
} finally {
assert unsafe != null;
unsafe.freeMemory(memoryAddress);
}
}
}
NIO Class action
JDK1.4 Introduced NIO, have access to Native Function library directly allocates out of heap memory , And then through a Java In the pile DirectByteBuffer Object operates as a reference to this memory .
Allocate a block of off heap memory as follows :
ByteBuffer bf = ByteBuffer.allocateDirect(10 * 1024);
Check the source code to see allocateDirect Function definition of :
/**
* Allocates a new direct byte buffer.
*
* <p> The new buffer's position will be zero, its limit will be its
* capacity, its mark will be undefined, and each of its elements will be
* initialized to zero. Whether or not it has a
* {@link #hasArray backing array} is unspecified.
*
* @param capacity
* The new buffer's capacity, in bytes
*
* @return The new byte buffer
*
* @throws IllegalArgumentException
* If the <tt>capacity</tt> is a negative integer
*/
public static ByteBuffer allocateDirect(int capacity) {
return new DirectByteBuffer(capacity);
}
You can see , This method returns a DirectByteBuffer object . Further inspection DirectByteBuffer The creation process of :
DirectByteBuffer(int cap) { // package-private
super(-1, 0, cap, cap);
boolean pa = VM.isDirectMemoryPageAligned();
int ps = Bits.pageSize();
long size = Math.max(1L, (long)cap + (pa ? ps : 0));
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;
}
In the process , Real memory allocation is used Bits.reserveMemory Method .Bits.reserveMemory() The main logic is as follows :
- Bits Class has a global variable totalCapacity, Used to identify DirectByteBuffer The total size of . Every time I apply for memory , Check whether the size limit is exceeded first ( It can be done by -XX:MaxDirectMemorySize Set up ). If the limit has been exceeded , It will call System.gc(), Looking forward to actively reclaiming a little off heap memory . Then sleep for a while , have a look totalCapacity Is it available . If the memory is still insufficient , Throw out OOM abnormal .
Creating DirectByteBuffer The end of the object , adopt Cleaner.create(this, new Deallocator(base, size, cap)) Created a Cleaner object . The object's function is : When DirectByteBuffer When the object is recycled , Release its corresponding off heap memory .
Recovery of out of heap memory
Out of heap memory is based on GC The recycling of
As mentioned above , Out of heap memory passes through in heap DirectByteBuffer Object to reference .DirectByteBuffer The object itself is very small , But it represents a large amount of memory allocated , It's called “ Iceberg ” object . When DirectByteBuffer The object is gc when , The off heap memory it refers to will also be recycled .
in other words , The recycling of off heap memory is DirectByteBuffer Triggered when recycled , and DirectByteBuffer The recycling of is in the heap GC What happened .
Recall the pile GC The mechanism of : When the new generation is full , It will trigger YongGC, If the object is not invalidated at this time , Will not be recycled ; After several times YongGC After that, the objects of the new generation that still survive are moved to the elderly generation . When the old generation is full Full GC.
If DirectByteBuffer The object survived several times YongGC Later, they were migrated to the elderly generation , Even if it fails, it can stay in the elderly generation . be relative to YongGC, In the old days Full GC The frequency of is relatively low . It doesn't happen in the elderly Full GC when , Invalid DirectByteBuffer Objects always occupy a large amount of out of heap memory without releasing .
Of course , There is another situation that can also trigger DirectByteBuffer Recycling . That's what I mentioned above , When out of heap memory is applied and space is insufficient , Will call System.gc() To tell the virtual machine what to do GC 了 . But this way is not reliable , Because it will only be triggered when there is insufficient memory space outside the heap . and , If set -DisableExplicitGC It's forbidden system.gc(), Then it can't be recycled .
Active recycling of off heap memory
Active recycling of off heap memory refers to the use of DirectByteBuffer Of clean Object for memory recovery . As shown below :
public class ByteBufferTest {
public static void main(String[] args) throws Exception {
long size = Runtime.getRuntime().maxMemory();
System.out.println(" The default maximum out of heap memory is :" + size / 1024.0 / 1024.0 + "mb");
ByteBuffer bf = ByteBuffer.allocateDirect(1024 * 1024 * 1024);
Thread.sleep(2000);
System.out.println("cleaner start");
// clean(bf);
ByteBuffer bf2 = ByteBuffer.allocateDirect(1024 * 1024 * 1024);
Thread.sleep(2000);
clean(bf2);
}
private static void clean(final ByteBuffer byteBuffer) throws Exception {
if (byteBuffer.isDirect()) {
Field cleanerField = byteBuffer.getClass().getDeclaredField("cleaner");
cleanerField.setAccessible(true);
Cleaner cleaner = (Cleaner) cleanerField.get(byteBuffer);
cleaner.clean();
}
// // The second method is to get cleaner
// if (byteBuffer.isDirect()) {
// Cleaner cleaner = ((DirectBuffer)byteBuffer).cleaner();
// cleaner.clean();
// }
}
}
In no way -XX:MaxDirectMemorySize Parameter to specify the maximum out of heap memory , The default out of heap memory is similar to heap memory , adopt Runtime.getRuntime().maxMemory() Can be obtained .
Then I applied 1024m Out of heap memory , And pass cleaner I did an out of heap memory recycling . Then apply again 1024m Out of heap memory . The operation effect is as follows :
The default maximum out of heap memory is :1753.0mb
cleaner start
If you comment out clean(bf) This business , There's no problem running . As mentioned above , When there is insufficient space to apply for out of heap memory , The system will call System.gc() To trigger Full GC, In order to achieve the purpose of reclaiming memory outside the heap .
If you comment out clean(bf) meanwhile , Appoint -XX:+DisableExplicitGC Parameter to prohibit explicit triggering gc, When applying for the second off heap memory , Will report OOM error , because System.gc() The call to is invalid . The running results are as follows :
Reference material
[1]. https://www.jianshu.com/p/17e72bb01bf1
[2]. https://juejin.im/post/5a9cb49df265da239706561a?utm_source=gold_browser_extension
[3]. https://www.jianshu.com/p/ae3847326e69
边栏推荐
- jvm命令归纳
- pycharm 打开多个项目的两种小技巧
- Where are the laravel framework log files stored? How to use it?
- 堆外内存的使用
- 力扣刷题,三数之和
- Database operation skills 6
- Zipkin安装和使用
- 220. Presence of repeating element III
- Study notes of automatic control principle -- correction and synthesis of automatic control system
- 网络安全漫山遍野的高大上名词之后的攻防策略本质
猜你喜欢

Introduction to excellent verilog/fpga open source project (30) - brute force MD5

Matlab 绘制阴影误差图

Node-v download and application, ES6 module import and export

(2006,Mysql Server has gone away)问题处理

Web overview and b/s architecture

堆外内存的使用

李沐d2l(四)---Softmax回归

CF1481C Fence Painting

Innovus卡住,提示X Error:

QtCreator报错:You need to set an executable in the custom run configuration.
随机推荐
Simple message mechanism of unity
ES6 modular import and export) (realize page nesting)
Probability model in machine learning
CSDN TOP1“一个处女座的程序猿“如何通过写作成为百万粉丝博主?
Introduction to excellent verilog/fpga open source project (30) - brute force MD5
PAT 甲级 A1034 Head of a Gang
Datax的学习笔记
机器学习中的概率模型
Innovus卡住,提示X Error:
NTT(快速数论变换)多项式求逆 一千五百字解析
Two tips for pycharm to open multiple projects
How to quickly learn a programming language
李沐d2l(六)---模型选择
Form form
Horizontal comparison of the data of the top ten blue chip NFTs in the past half year
CF1481C Fence Painting
Day06 homework -- skill question 2
Datawhale panda book has been published!
Advanced mathematics | Takeshi's "classic series" daily question train of thought and summary of error prone points
公告 | FISCO BCOS v3.0-rc4发布,新增Max版,可支撑海量交易上链