什么是运行时数据区?
虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域有各自的用途,以及创建和销毁的时间。
程序计数器
1.是一块比较小的内存空间,可以看做线程所执行字节码过程中的行号指示器。 他是程序控制流的指示器,分支,循环,跳转,异常处理,线程恢复都需要依赖程序计数器。
举例说明
虚拟机栈
1.线程私有的(一个线程只有一个虚拟机栈(方法栈),每个线程之间是相互隔离的)
2.方法执行后会创建栈帧,存储局部变量表等信息。 局部变量表:他可能是基本数据类型,也可能是引用数据类型,引用类型是一个变量话指向我们堆中的对象。
操作数栈:如果需要有一些运算时候就需要操作数栈 a+b
动态连接:一个方法调用另一个方法,需要通过动态连接去找到对应方法的内存地址
返回地址:不管执行成功或者是执行失败,都要有返回结果。return
3.方法执行栈原则,先进后出
4.栈的深度大于虚拟机所允许的深度时候 StackOverflowError 在递归调用3万多次时候会出现。
5.栈里面运行方法,存放的局部变量,变量名所指向的值(常量值,对象值)都是存放到我们的堆空间的
6.栈一般不设置大小,栈所使用空间很小,可以通过-Xss1M进行设置,不设置默认是1M。如果栈设置的小,所对应的线程数就更多
7.随着线程消亡而消亡。
8.不需要垃圾回收
本地方法机栈
所发挥的作用是非常相似的其区别只是虚拟机栈为虚拟机执行Java方法服务,而本地方法栈则是为虚拟机使用到的本地(Native)方法服务
jVM堆
-
线程所共享的,存放对象的实例,内存中最大的区域
-
虚拟机启动后堆内存就被分配
-
GC主要管理的区域
-
可分为新生代、老年代(新创建的对象时在新生代,如果存活时间很长就分配到老年代)
-
新生代又可以细分为伊甸区,伊甸一区,伊甸二区 分配比例是8:1:1
-
通过-Xmx,-Xms 调节堆的大小
-
堆内存不足,会抛出堆溢出异常
-
内存分配在多线程创建对象时会造成对象分配竞争,为了解决这种问题可以分配出多个私有线程的缓存区(TLAB)
jVM堆该如何在堆中分配内存
-
指针碰撞,内存规整有序的情况下。
-
空闲列表,内存不规整的情况下,把内存空的地址放入列表中,由空闲列表为对象分配存储位置。
内存是否规整是有垃圾回收器是否有空间压缩整理能力决定
1). Serial、ParNew 等垃圾回收器带空间压缩整理
2). CMS这种基于清楚算法垃圾回收器,只能才用空闲列表分配内存
jVM方法区
方法区(Method Area)与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。
运行时常量池
用于存放编译期生成的各种字面量与符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。