1.内存空间
方法区:类的信息,常量,静态,这一块的区域,一般是不进行回收的,但是如果满了以后,有一个叫做Full GC的也会回收方法区的东西
堆内存区heap:一些new出来的obj,堆内存区,是辣鸡回收机制主要回收内存的地方
栈区stack:主要存放基本数据类型,局部变量
本地方法栈:这里是java要使用别的语言库的一个内存区,所有的func要加native修饰
2.垃圾回收机制原理
以对象是否可达,最为判断点
如果一个obj没有被别的对象引用,那么这个对象就是不可达,反之就是可达的对象
finalize()方法是回收机制在回收前会调用的一个方法,这里肯定是要new一个obj的子类,直接new一个obj肯定不行,因为finalize()方法是一个需要子类重写的方法.
System.gc() 会提示垃圾回收机制进行垃圾回收,但是不是立即执行的
3.堆内存划分:
这是一个很核心的知识点
堆内存划分为: 新生代 + 老年代
其中 新生代 = eden + s0(又叫from区) + s1(又叫to区)
eden区:主要的内存回收发生在这里
s0区:
s1区:
这2个区必须要一起来讲:s0区和s1区的内存大小一样,当我们eden区的obj,在进行了若干次的被引用后,会跑到s0区,在一段时间过后,如果s0区的对象,有一些不可达了,那么s0区可达的对象,会被全部复制到s1区,然后gc会把s0区所有不可达的obj删除,然后同样,再过一段时间以后,s1区如果有一些不可达的对象需要被回收,那么s0会从s1区复制s1区所有的可达的对象,然后再把s1区所有的不可达对象删除 --> 以上就被称之为复制算法
复制算法有一个很大的优点就是:避免了碎片化
默认 新生代:老年代 = 1 :2
新的obj在引用计数到了15次以后,就会从新生代跑到老年代去,这里的引用计数法,跟oc里面的引用计数,几乎是一模一样,这里用"几乎"是怕有不同的地方,在我看来原理就是完全一样的
3.垃圾回收机制的算法
引用计数法:这里几乎就是跟oc中的引用计数法一样,在这里被jvm淘汰,是因为循环引用...但是在oc里面使weakself来避免循环引用
根搜索法:GCRoots
如果一个对象,跟GCRoots对象连在一起,那就说明,这个对象是可达的,那么就不会被回收
方法区,本地方法栈,虚拟机栈,这些都可以作为一个GCRoots对象
标记清除算法:
用状态码标定一个对象是否存活,然后垃圾回收机制会根据这个状态码,来进行回收
但是,这里会产生一个碎片化的问题,这种单个回收,肯定会带来碎片回收的问题,回收也会有残余,这个涉及到硬盘硬件原理...
所以,这里不适合做新生代的垃圾回收处理,一般都用于老年大的垃圾回收.
标记压缩算法:
把可达对象和不可达对象,分别划为2个阵营,这样,在清除不可达对象的时候,就可以一把清除了
分代算法:
对内存中的垃圾按照实际情况综合清理
4.三中GC
minorGC:主要用于回收新生代的垃圾
majorGC:主要用于回收老年代的垃圾
fullGC:新生代和老年代都会回收