栈(线程):
java虚拟机栈:属于线程的私有区域,每个线程在创建的时候都会创建一个虚拟机栈,生命周期与线程一直,线程退出时,线程的虚拟机栈也会被回收;虚拟机栈内部保存一个个栈帧,每次调用方法都会进行压栈,jvm对栈帧的操作只有压栈和出栈两种操作,方法调用结束时会进行出栈操作.
栈帧:一个线程执行到一个方法的时候,java虚拟机马上会给这个方法划分一块独立的内存(用来存储局部变量),把一个方法对应的内存区叫做栈帧内存区.
包括:局部变量表,操作数栈,动态链接,方法出口
程序计数器
操作系统:存放下一条指令所在单元的地址的地方
jvm: 当前线程所执行的字节码的行号指示器,保证线程切换后能回复到正确位置
作用:记录程序运行的位置,如果当前线程在执行过程中被挂起了,没有抢到cpu执行的时间片,程序计数器能保证线程再次执行的时候能在上次挂起的地方继续执行下去.
操作数栈
临时的内存区域,用来存放程序在运行过程中的操作数的一个中转临时的内存区域.
堆(heap)
堆(heap):几乎所有创建的java对象的实例,都是直接被分配在堆内存上的.堆被所有线程共享,在堆上的区域,会被垃圾回收区域进一步划分,例如新生代,老年代的划分.java虚拟机在启动的时候,可以使用"Xmx"之类的参数设置堆区域的大小.
方法区
方法区和堆一样被所有的线程共享,存储被虚拟机加载的元(Meta)数据,包括类信息,常量,静态变量,即时编译后的代码数据等.
方法区是java虚拟机的一种规范.由于方法区中存储的数据和堆中的数据一致,实际上也是堆,因此在不同jdk版本方法区的实现方式不一样.
jdk1.7之前叫永久代,jdk1.8之后是"元数据空间"和堆结合起来
本地方法栈
本地方法(native 修饰的方法)在运行过程中需要的区域
可达性分析算法:
将"GC Roots"对象作为起点,从这些节点开始向下搜索 引用的对象,找到的对象都标记为非垃圾对象,其余为标记的都是非垃圾对象.
"GC Roots":线程栈的本地变量,静态变量,本地方法栈的变量等
GC 垃圾回收机制:
jvm的内存空间大的方面可分为:新生代空间(Young),老年代空间(old)
1)Eden(伊甸园)区域:用来存放使用new或者newInstance等方式创建的对象,默认这些对象都是存放在Eden区,除非这个对象太大,或者超出了设定的阈值-XX:PretenureSizeThresold,这样的对象会被直接分配到Old区域。
2)2个Survivous(幸存)区域:一般称为S0,S1,理论上他们一样大。
第一次GC
如果一直不断的创建对象,当Eden区被占满,此时会开始做 Young GC也叫 Minor GC
- 第一次GC 时Survivous 中s0和s1区都为空,将其中一个作为 To Survivous(用来存储Eden区域执行GC后不能被回收的对象),比如:将S0作为To Survivous,则S1为From Survivous。
2)将Eden区域经过GC不能被回收的对象存储到To Survivous(S0)区域(此时Eden区域的内存会在垃圾回收的过程中全部释放),但如果To Survivous(S0)被占满了,Eden中剩下不能被回收对象只能存放到Old区域。
3)将Eden区域空间清空,此时From Survivous区域(S1)也是空的。
4)S0与S1互相切换标签,S0为From Survivous,S1为To Survivous。
每执行一个gc未被清理的对象分代年龄就是加一,当对象的分代年龄为15的时候,就会被转移到老年代空间中
如果老年代内存被占满了,会报栈溢出OOM的错误 OutOfMemoryError
在OOM之前会执行一次 full GC
full GC 清理整个堆,包括新生代和老年代
Stop-The-World:
在新生代进行的GC叫做minor GC,在老年代进行的GC都叫major GC,Full GC同时作用于新生代和老年代在垃圾回收过程中经常涉及到对对象的挪动(比如上文提到的对象在Survivor 0和Survivor 1之间的复制),进而导致需要对对象引用进行更新。为了保证引用更新的正确性,Java将暂停所有其他的线程,这种情况被称为“Stop-The-World”,导致系统全局停顿。Stop-The-World对系统性能存在影响,因此垃圾回收的一个原则是尽量减少“Stop-The-World”的时间。
不同垃圾收集器的Stop-The-World情况,Serial、Parallel和CMS收集器均存在不同程度的Stop-The-Word情况;而即便是最新的G1收集器也不例外。
Java中一种全局暂停的现象,jvm挂起状态
全局停顿,所有Java代码停止,native代码可以执行,但不能和JVM交互
多半由于jvm的GC引起,如:
1.老年代空间不足。
2.永生代(jkd7)或者元数据空间(jkd8)不足。
3.System.gc()方法调用。
4.CMS GC时出现promotion failed和concurrent mode failure
5.YoungGC时晋升老年代的内存平均值大于老年代剩余空间
6.有连续的大对象需要分配
除了GC还有以下原因:
1.Dump线程--人为因素。
2.死锁检查。
3.堆Dump--人为因素。
Full GC 是清理整个堆空间—包括年轻代和老年代。
在GC的过程中会发生全局停顿现象,是为了彻底清理垃圾