?
1 java内存分为:程序计数器(当前线程所执行字节码的行号指示器,字节码解释器要通过改变这个计数器的值来选择下一条字节码指令,分支、循环、异常处理等。每条线程都有一条独立的程序计数器,属于线程私有的内存区)、
java虚拟机栈(也是线私有的,存储局部变量、操作栈,每个方法执行时创建一个栈帧,执行过程就是栈的出栈入栈操作)、
本地方法栈(执行native方法)、
年轻代堆(eden、from survivor、to survivor)、年老代堆(经过几次垃圾回收,保存下来的)、
持久代堆(也叫方法区,保存常量池和类型数据信息,不会被回收)、
直接内存(使用native方法直接分配堆外内存,再通过堆内的DirectByteBuffer作为这块内存的引用进行操作)
2 对象访问有两种:通过句柄池和直接通过指针,句柄池的好处是垃圾回收后,不需要改变对象引用,只要改变句柄引用;直接指针的好处是效率较高。
引用《深入java虚拟机第二章》
解释了minor gc和major gc,和两个survivor区之于复制收集算法的意义
http://blog.sina.com.cn/s/blog_620ccfbf0100t05y.html
?
3 jvm内存机制
http://java.chinaitlab.com/Jvm/852310.html
java内存中的四种引用解析,强引用、弱引用、软引用、虚引用
?http://java.chinaitlab.com/oop/716371_3.html
?http://softbbs.pconline.com.cn/6882929.html
4 垃圾回收算法
4.1 引用计数,效率高,但是无法解决无用对象循环引用的问题。及时引用计数大于0,但却不可用。
4.2 根对象可达,java虚拟机使用的方式。可以作为根对象的有:虚拟机栈帧中引用的对象,方法区中(持久区)类静态属性引用的对象(类静态属性在创建实例之前就已经为这个属性分配好空间,创建好实例,在所有的类实例中共享),方法区中常量引用的对象(比如常量字符串),本地方法栈中引用的对象(native方法)。
4.3 引用强度,强(即传统理解的引用,obj=new obj()),软(softReference,在内存溢出之前,GC会将这部分纳入回收范围,进行二次回收,如果还是没有足够内存,那么OOM),弱(weakReference,一旦GC进行回收,无论内存是否充足都会被回收),虚(有虚引用不会影响生命周期,无法通过虚引用来获得一个对象,唯一作用是对象被回收时能得到一个系统通知,PhantomReference)
4.4 对象在回收之前会调用仅有一次finalize(),可以在finalize中自救,把自己被引用。只有当对象覆盖finalize()方法才会被放入执行finalize()的队列。不建议使用这个,可以用try{} finally代替。
4.5 java回收算法
标记清除法,效率低下,会产生内存碎片。
复制收集算法,较为主流的算法,分区,eden,survivor,将未被回收的对象移动到survivor区,然后一次性清理eden区。这种算法适用于对象存活率不高的情况,要牺牲一部分分配空间,一般来说eden:survivor=8:1。
当对象存活率很高的时候,复制收集算法的效率会出现问题,所以有了标记-整理算法。把所有存活对象整理到一端,再把另一端直接清理掉。
分代算法,java内存一般都分为新生代和年老代,根据两个区域对象存活率的特点,分别采用了复制-收集算法和标记-清理(标记-整理)算法。
4.6 垃圾收集器
serial收集器,单线程收集。很可恶,会停掉其他用户线程。糟糕的用户体验。但是适用于client端,因为产生的垃圾量少,回收快,几十毫秒解决。
parNew收集器,和serial一样。区别是收集时采用多线程机制。
CMS收集器,可以让收集线程和用户线程并发执行,可惜的是作为年老代的收集器,只能和上面两个不靠谱的收集器一起配合使用。它是以最短停顿时间为目标的年老代收集器,使用mark-sweep算法(标记-清除)。回收步骤是初始标记(stop world),并发标记,重新标记(stop world),并发清除。stop world的时间很短,所以可以认为是用户线程并发的收集器。
parallel scavenge收集器,是并发收集器,可以和用户线程并存。可以通过参数控制吞吐量=用户线程时间/(用户时间+垃圾收集时间),前台程序适用低吞吐量,减少用户操作每次停顿的时间;而后台程序适用于高吞吐量,尽快完成后台的计算。也称作吞吐量优先收集器。该收集器还能设置自适应模式,会根据实际情况动态调整吞吐量。
serial old收集器和serial一样,用于年老代收集。使用标记整理算法。
parallel old收集器,用于和parallel scavenge配合使用的年老代收集器,是parallel scavenge的最佳搭档。
G1(garbage first)收集器,最前沿的,jdk1.6进入试用期。采用标记-整理算法,并且对新生区分区,分区有不同的优先级,优先收集内存较满的区域。有着很高的并发和较低的停顿,也算是敏捷的一种收集器。
5? 基本经验
minor gc是运行在新生代的gc,major GC是运行在年老代的GC,比minor慢十倍。
大对象很有可能直接进入年老代,程序中尽量避免短命大对象(数组、列表)。
一次minor没被收集,从eden进入survivor,每过一次GC,survivor加一岁,直到N岁进入年老区。
?
?
?
?