JVM 内存管理


文章为《深入分析JavaWeb》的第八章的笔记与自己理解的部分


物理内存与虚拟内存

物理内存与虚拟内存只是针对操作系统来讲的。
内存的使用对于操作系统中的应该用程序(包括JVM)来说,都应该是透明。
物理内存的虚拟内存之间的分页交换,由缺页中断触发。

其实这部分内容只是铺垫内存的类别及概念。

内核空间与用户空间

内核空间与用户空间也是操作系统衍生出来的概念。
为了操作系统的稳定,避免普通应用程序代码干扰系统正常运行。
操作系统设计的时候,就区分了不同权限。R0到Rn。
操作系统所处的代码与内存空间就称为内核空间。
内核空间的内存,普通应用程序是无法访问与修改的。
然后用户空间就是供普通应用程序使用的空间。
但每个应用程序使用的空间与是互相独立的。

需要使用内存的组件

Java 堆

Java 堆是用于存储Java对象的内存区域,堆的大小在JVM启动时就一次向操作系统申请完成,通过-Xmx和-Xms来控制最大小和最小大小。
一旦分配完成,大小就将固定。不能重新申请,也不能在闲时,退给操作系统。

Java 堆中的内存由JVM来控制的。对象创建由Java应用程序控制,但是对象占用空间释放由管理堆内存的垃圾收集器来完成。

线程

JVM 运行实际程序的实体是线程,当然线程需要内存空间来存储一些必要的数据。每个线程创建时JVM都会为它创建一个堆栈,大小根据不同的JVM实现,不同。通常在256K-756K之间。线程所占空间相比堆空间来说比较小。

类和加载器

在Java中的类和类加载器本身同样需要存储空间,在Sun JDK中它们也是存储在堆中,这个区域叫PemGen区。

需要注意的一点是JVM是按需要来加载类的。JVM只会加哉那些在你的代码 中明确有使用的类到内存中。要查看JVM到底加载了哪些类,可能在启动参数加上-verbose:class
理论上使用的 Java 类越多,需要占用的内存也会越多。

NIO

Java在1.4以后增加了NIO类库,引入了一种新IO方式。NIO使用ByteBuffer.allocatteDirect()方法分配内存,这些内存不是堆中,而是在本机中。直接产生的数据交互都是在内核空间中发生。这样就不需要复制来复制去,提高效率。但如果频繁的发送很小的数据,这种系统调用的开销可能会抵消数据在内核空间与堆上复制的开销。

JNI

JNI技术使用的本地代码可以调用Java方法,也就是通常 所说的native memory。实际上Java运行本身也是依赖于JNI代码来实现类库的功能,如文件操作,网络操作等。

JVM 内存结构

JVM是按运行时数据据的存储 结构来划分内存结构。
在Java虚拟机规范中把java运行时数据划分为6种:

  • PC寄存器数据
  • java 栈
  • 方法区
  • 本地方法区
  • 运行时常量池

未完待写