Java使用内存的组件

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012484172/article/details/79967733

Java堆:Java堆是用于存储Java对象的内存区域,堆的大小在JVM启动时就一次向操作系统申请完成,通过-Xmx和-Xms两个选项来控制大小,Xmx表示堆的最大大小,Xms表示初始大小。一旦分配完成,堆的大小就将固定,不能在内存不够时再像操作系统重新申请,同时当内存空闲时也不能将对于的空间交还给操作系统。在Java堆中内存空间的管理由JVM来控制,对象创建由Java应用程序控制,但是对象所占的空间释放由管理堆内存的垃圾收集器来完成。根据垃圾收集算法的不同,内存回收的方式和时机也不同

线程:JVM运行实际程序的尸体是线程,当然线程需要内存空间来存储一些必要的数据。每个线程创建JVM都会为他创建一个堆栈,堆栈的大小根据不同的JVM实现而不同,通常在256KB~756KB之间。

类和类加载器:在Java中的类和类加载器本身同时需要存储空间,在Sun JDK中它们也被存储在堆中,这个区域叫做永久代(PermGen区)。JVM是按需来加载类的,它只会加载那些在你的应用程序中明确使用的类到内存中。在启动参数上加上-verbose:class 可以查看JVM到底加载了哪些类。通常情况下JVM只会加载一个类到内存一次,但是如果是自己实现的类加载器会出现重复加载的情况,如果PermGen区不能对已经失效的类做卸载,可能会导致PermGen区内存泄漏。一个类能够被卸载,需要满足下面三个条件:
1)在Java堆中没有对表示该类加载器的ClassLoader对象的引用
2)Java堆没有对表示类加载器加载的类的任何Class对象的引用
3)在Java堆上该类加载器加载的任何类的所有对象都不再存活(被引用)

NIO:NIO使用java.nio.ByteBuffer.allocateDirect方法分配内存,这种方式是通常说的NIO direct memory。ByteBuffer.allocateDirect分配的内存使用的是本机内存而不是Java堆上的内存,这说明每次分配内存时会调用操作系统的os::malloc函数。这种方式的好处在于——如果数据和网络或者磁盘交互都在操作系统内核空间中发生,不需要将数据复制到Java内存中,执行这种I/O操作要比一般的从操作系统的内核空间到Java堆上的切换操作快得多,因为它们可以避免在Java堆与本机堆之间复制数据,但如果I/O频繁的发生很小的数据,这种系统调用的开销可能会抵消数据在内核空间和用户空间复制带来的好处。ByteBuffer 对象会自动清理本机缓冲区,但这个过程只能作为Java堆GC的一部分来执行,因此它们不会自动响应施加在本机堆上的压力。GC仅在Java堆被填满以至于无法分配堆内存时发生,在Java应用程序中显示请求(调用System.gc())时也会触发GC。但是显示请求GC会影响应用程序的性能,一般会通过设置-XX:+DisableExplicitGC来控制System.gc()的影响,但是又会导致NIO direct memory内存泄漏的问题。

JNI:JNI技术是的本机代码可以调用Java方法,这部分所使用的内存是通常说的native memory。实际上Java运行时本身也依赖于JNI代码来实现类库功能,例如文件操作、网络I/O或者其他系统调用。JNI会增加Java运行时的本机内存占用。

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页