JVM运行时的内存划分
jvm运行时分为线程私有区和线程共享区两个部分:
线程私有
程序计数器:
记录当前线程跑到哪一行代码了
虚拟机栈:
描述java方法的内存模型
本机方法栈:
native方法内存模型
HotspotJVM中本地方法栈与虚拟机栈合二为一
线程共享
堆:
所有对象实例以及数组对象
方法区:
已加载的类信息,一个类的类型,有什么属性,方法,都在方法区记录
运行时常量池:
方法去的一部分,存放的是字面量与符号引用(字面量:直接写出来的值比如 int a = 10)
(符号引用:通过包名,类名先找到类,然后new对象。不同包的不同类就是不同的符号引用)
有关GC
(如何判断对象是否存活->对象的自我拯救(finalize方法)->如何进行垃圾回收)
引用计数法:
有一个地方引用对象,+1,该引用为空时,-1,为0时,说明不在存活(无法解决循环引用问题,我中有你,你中有我)
导致无用对象无法判断存活进而无法回收从而造成内存泄漏。
可达性分析法:
哪些对象可以作为GC Roots :
栈中的引用对象
类中的静态变量,常量引用的对象
***** JDK1.2关于引用的扩充 *****
强引用:程序中普遍存在的,类似于直接new称为强引用.
对象被任意一个强引用指向,即便抛出OOM异常,也无法回收被强引用指向的对象。
软引用:描述有用但不必须对象(缓存),SoftReference类描述软引用。
若对象只被软引用指向,当前内存够用时不回收,当即将抛出OOM异常时,一次性回收所有仅被
软引用指向的对象。
弱引用:WeakReference
仅被弱引用指向的对象,无论内存是否够用,当GC开始时,都会回收掉仅被弱引用指向的对象。
虚引用:PhantomReference
虚引用完全不对对象的生存周期产生任何影响,也无法通过虚引用取得一个对象实例。
当虚引用指向的对象被GC时,JVM会发回一个回收通知。
-> 对象的自我拯救finalize JDK1.9 @Deprecated
-若对象所在的类覆写了finalize()
-该对象的finalize()未被JVM调用过,JVM会调用此对象的finalize()
-该对象的finalize()被JVM调用过,此对象被标记为不再存活,可以进行GC
-对象所在的类没有覆写finalize(),此对象直接标记为不再存活,可以进行GC
final、finally、finalize
-> 垃圾回收算法
将堆空间分为新生代与老年代,对象默认在新生代产生,
新生代对象"朝生夕死",新生代对象的存活率很低( <= 2%)
Java采用分代回收算法,新生代采用复制算法,老年代采用标记-整理算法
-Xss(设置栈的大小)128k
-Xms(设置堆的最小值)10m
-Xmx(设置堆的最大值)
-Xmn(设置新生代内存大小)
新生代GC比老年代的GC速度快10倍以上,发生频率高的多。
为何老年代不采用复制算法?
老年代对象存活率很高,若采用复制算法,复制开销远高于新生代,不适合复制算法。
禁止指令重排:
1.volatile代码既不会提前也不会滞后
2.volatile代码前的所有代码一定全部执行完毕,volatile之后的所有代码一定还未开始