JVM
一.jvm基本内存模型
1.栈区
栈可以分为虚拟机栈和本地方法栈,我们平时主要用的还是虚拟机栈,栈这种数据结构想必学过数据结构的都知道,特点就是后进先出。
java虚拟机栈是线程私有的,生命周期与线程相同。每个方法执行的时候都会创建一个栈帧,用于存放局部变量表、操作栈、动态链接和方法出口等,每个方法从开始执行到结束对应一个栈帧入栈到出栈的过程。而我们通常说的栈指的是局部变量表,存放在编译期间可知的8种基本类型、对象引用和指令地址。局部变量表是在编译期间完成分配,当进入一个方法时,这个栈中的局部变量分配内存大小是确定的。
而在栈区可能发生的异常包括StackOverFlowError和 OutOfMemoneyError。当线程请求栈深度大于虚拟机所允许的深度就会抛出StackOverFlowError错误;虚拟机栈动态扩展,当扩展无法申请到足够的内存空间时候,抛出OutOfMemoneyError。
本地方法栈为虚拟机使用到本地方法服务(native),功能和特点类似于java虚拟机栈,均具有线程隔离的特点以及都能抛出StackOverflowError和OutOfMemoryError异常,不同的是,本地方法栈服务的对象是JVM执行的native方法,而虚拟机栈服务的是JVM执行的java方法。
2.堆区
堆区是jvm中内存较大的一块,主要用来存放对象实例,被所有线程共享,在虚拟机启动时创建,是gc的主要区域。
通常可分为年轻代、年老代和永久代,而年轻代又可以分为Eden、From survivor 和 To survivor三个区,Eden区存放新创建的对象,From survivor 和 To survivor存放gc后幸存的对象,默认的比例是8:1:1
3.方法区
被所有线程共享区域,用于存放已被虚拟机加载的类信息,常量,静态变量等数据。被Java虚拟机描述为堆的一个逻辑部分。习惯是也叫它永久代(permanment generation)
垃圾回收很少光顾这个区域,不过也是需要回收的,主要针对常量池回收,类型卸载。
常量池用于存放编译期生成的各种字节码和符号引用,常量池具有一定的动态性,里面可以存放编译期生成的常量;运行期间的常量也可以添加进入常量池中,比如string的intern()方法。
4.程序计数器
当前线程所执行的行号指示器。通过改变计数器的值来确定下一条指令,比如循环,分支,跳转,异常处理,线程恢复等都是依赖计数器来完成。
Java虚拟机多线程是通过线程轮流切换并分配处理器执行时间的方式实现的。为了线程切换能恢复到正确的位置,每条线程都需要一个独立的程序计数器,所以它是线程私有的。
唯一一块Java虚拟机没有规定任何OutofMemoryError的区块。
二.堆中的分区
1.具体的分区及其特点
JVM中堆空间可以分成三个大区,新生代、老年代、永久代。
新生代可以划分为三个区,Eden区(Eden Memory),两个幸存区(S0和S1)。
所有新创建的 Object 首先被放在 新生代(Young Generation) 内存区。如果 Young Generation 内存区满了,则执行 Garbage Collection ,这种 GC 称为 Minor GC。
绝大多数新建的 Object 被放在 Eden Memory ,如果 Eden Memory 内存满了,则进行 GC 操作,同时把未被 GC 的 Object 移动到 S0 或 S1 中。 此时 Minor GC 也会检查和移动 S0 和 S1 中的对象。 最后使 S0,S1 其中一个置为空。多次 GC 后仍然未被 GC 的 Object 将被移动到 Old Gen 内存区中
2.参数设置
在JVM运行时,可以通过配置以下参数改变整个JVM堆的配置比例
1.JVM运行时堆的大小
-Xms堆的最小值
-Xmx堆空间的最大值
2.新生代堆空间大小
-XX:NewSize新生代的最小值
-XX:MaxNewSize新生代的最大值
-XX:NewRatio设置新生代与老年代在堆空间的大小
-XX:SurvivorRatio新生代中Eden所占区域的大小
3.永久代大小调整
-XX:MaxPermSize
4.其它
-XX:MaxTenuringThreshold,设置将新生代对象转到老年代时需要经过多少次垃圾回收,但是仍然没有被回收

浙公网安备 33010602011771号