运行时数据区域
1、程序计数器:
较小的内存空间,线程私有,当前线程所执行的字节码的行号指示器,字节码解释器工作时,就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,如果执行的Native方法,计数器的值为空,不会产生异常情况。
2、Java虚拟机栈:
线程私有,描述的是Java方法执行的内存模型,每个方法对应一个栈帧(Stack Frame)存储局部变量表、操作栈、动态链接、方法出口等信息,每一个方法被调用到执行完成,对应一个栈帧在虚拟机栈中的入栈到出栈。
局部变量表存放编译期可知的各种基本数据类型、对象引用、returnAddress类型,long和double类型的数据会占2个局部变量空间(slot),其余占一个,局部变量表所需的内存空间在编译期间完成分配。
当线程请求的栈深度大于JVM所允许的深度,抛出StackOverFlowError;
当JVM可以动态扩展时,无法申请到足够的内存时会抛出OutOfMemoryError
3、本地方法栈:
与虚拟机栈类似,区别是本地方法栈为JVM使用到的Native方法服务
有的虚拟机(如:HotSpot)直接把本地方法栈和虚拟机栈合二为一
4、Java堆:
JVM所管理内存中最大的一块,线程共享,JVM启动时创建,存放对象实例,垃圾收集器管理的主要区域。
Java堆可以处于物理上不连续的空间,只要逻辑上是连续的。
当堆中没有内存完成实例分配,并且堆也无法再扩展时,会抛出OutOfMemoryError
5、方法区:线程共享,存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
垃圾收集行为较少,内存回收的目标主要是常量池的回收、类型的卸载
当无法满足内存分配需求时,抛出OutOfMemoryError
运行时常量池:
方法区的一部分,Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项是常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。
对象的访问方式
1、使用句柄:
2、直接访问:
调节参数
设置堆大小
-Xms -Xmx
设置栈大小:
-Xss
设置常量池的大小:
-XX:PermSize -XX:MaxPermSize