
线程私有的内存区域,一块较小的内存空间,作用是当前线程所执行的字节码的行号指示器
JVMStacks,也是 线程私有 的,生命周期与线程相同
描述的是Java方法执行的内存模型:每个方法被执行的时候会同时创建一个栈帧用于存储局部变量表、操作栈、动态链接、方法出口等信息。每个方法被调用直至执行完成的过程,就对应一个栈帧在虚拟机栈中从入栈到出栈的过程
一般网上说的栈内存指的是这里的局部变量表,局部变量表的内存空间在编译期间完成分配
如果线程请求的栈深度大于虚拟机所允许的深度,将抛出 StackOverflowError,如果虚拟机栈动态扩展时无法申请到足够的内存会抛出 OutOfMemoryError
与JVMStacks的区别是,为虚拟机使用到的Native方法服务
被所有线程共享的一块内存区域,在虚拟机启动时候创建。对于大多数应用来说,Java堆(Java Heap)是Java虚拟机所管理的内存中最大的一块。此内存区域的唯一目的就是存放对象实例
Java堆也是垃圾收集器广利的主要区域,因此很多时候也被称作”GC堆“
由于现在收集器基本都是采用的分代收集算法,所以Java堆中还可以细分为:新生代和老年代,再细致一点的有Eden空间、From Survivor空间、To Survivor空间
当前主流虚拟机都是按照可扩展来实现的(通过-Xmx和-Xms控制)。如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出 OutOfMemoryError
-Xms:设置进程堆内存的最小大小-Xmx:设置进程堆内存的最大大小-Xmn:设置堆内存新生代的大小与Java堆一样,是各个线程共享的内存区域,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。当方法区无法满足内存分配需求时,将抛出 OutOfMemoryError
是 方法区 的一部分。Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。String.intern()方法可以在运行期间将新的常量放入池中
JDK1.4中新加入的NIO(New Input/Output)类,引入了一种基于通道(channel)与缓冲区(buffer)的I/O方式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆里面的DirectByteBuffer对象作为这块内存的引用进行操作。
如果使用句柄访问方式,Java堆中将会划分出一块内存来作为句柄池,reference
中存储的就是对象的句柄地址,而句柄中包含了对象实例数据和类型数据各自的
具体地址信息,如图所示。

如果使用直接指针访问方式,Jva堆对象的布局中就必须考虑如何放置访问类型
数据的相关信息,reference中直接存储的就是对象地址,如图所示

这两种对象的访问方式各有优势,使用句柄访问方式的最大好处就是reference中存储的是稳定的句柄地址,在对象被移动(垃圾收集时移动对象是非常普遍的行为)时只会改变句柄中的实例数据指针,而reference本身不需要被修改。
使用直接指针访问方式的最大好处就是速度更快,它节省了一次指针定位的时间开销,由于对象的访问在Jva中非常频繁,因此这类开销积少成多后也是一项非常可观的执行成本。就这里讨论的主要虚拟机Sun HotSpot而言,它是使用第二种方式进行对象
出现Java堆内存溢出时,异常堆栈信息“java.lang.OutOfMemoryError”会跟着进一步提示“Java heap space”。要解决这个区域的异常,一般的手段是:
对于HotSpot虚拟机来说,栈容量只由-Xss参数设定。但是这部分抛出 StackOverflowError 的情况比OOM要常见
如果要向运行时常量池中添加内容,最简单的做法就是使用String.intern()方法。该方法的作用是:如果池中已经包含一个等于此String对象的字符串,则返回代表池中这个字符串的String对象;否则,将此String对象包含的字符串添加到常量池中,并且返回此String对象的引用。
可以通过-XX:PermSize 和 -XX:MaxPermSize限制方法区的大小,从而间接限制其常量池的容量
方法区用于存放Class的相关信息,如类名、访问修饰符、常量池、字段描述、方法描述等。对于这个区域的测试,可以在运行时产生大量的类去填满方法区,直到溢出。
该部分可铜鼓 -XX:MaxDirectMemorySize指定,如果不指定,则默认与Java堆的最大值(-Xmx指定)一样。虽然使用DirectByteBuffer分配内存也会抛出内存溢出异常,但它抛出异常时并没有真正向操作系统申请分配内存,而是通过计算得知内存无法分配,于是手动抛出异,真正申请分配内存的方法是unsafe.allocateMemory()