公众号:知识浅谈
为了不侵犯作者版权,选择了转载,我补充了很多自己的理解。
垃圾回收相关
- GC Root都有哪些?
- 垃圾回收器的基本原理
- 垃圾回收器不可以马上回收内存
- 怎么主动通知虚拟机进行垃圾回收
- java中会存在内存泄漏吗
- minor gc运行的很频繁可能是什么原因引起的?
- minor gc运行的很慢有可能是什么原因引起的?
- 垃圾回收的优点以及原理
- GC是什么,为什么要有GC?
- GC算法
GC Root都有哪些?
1、虚拟机栈中引用的对象
比如:各个线程被调用的方法中使用到的参数、局部变量等。
2、本地方法栈内JNI(通常说的本地方法)引用的对象
3、方法区中类静态属性引用的对象
比如:Java类的引用类型静态变量
4、方法区中常量引用的对象
比如:字符串常量池(string Table) 里的引用
5、所有被同步锁synchronized持有的对象
6、Java虚拟机内部的引用。
基本数据类型对应的Class对象,一些常驻的异常对象(如:
NullPointerException、OutOfMemoryError) ,系统类加载器。
7、根据用户所选用的垃圾收集器以及当前回收的内存区域不同,还可以有其他对象“临时性”地加入,共同构成完整GC Roots集合。
垃圾回收器的基本原理
对于GC来说,当程序员创建对象时,GC就开始监控这个对象的地址、大小以及使用情况。通常,GC采用有向图的方式记录和管理堆(heap)中的所有对象。通过这种方式确定哪些对象是”可达的”,哪些对象是”不可达的”。当GC确定一些对象为”不可达”时,GC就有责任回收这些内存空间。
垃圾回收器不可以马上回收内存
垃圾收集器不可以被强制执行,但程序员可以通过调研System.gc方法来建议执行垃圾收集。
记住,只是建议。一般不建议自己写System.gc,因为会加大垃圾收集工作量。
怎么主动通知虚拟机进行垃圾回收
程序员可以手动执行System.gc(),通知GC运行,但是Java语言规范并不保证GC一定会执行。
java中会存在内存泄漏吗
会存在内存泄漏。
说明:内存泄漏是指一个不再被程序使用的对象或变量还在内存中占有存储空间。
Java garbage collector自动释放哪些内存里面程序不在需要的对象, 以此避免大多数的其他程序上下文的内存泄漏. 但是Java应用程序依旧会有相当的内存泄漏。
- 静态集合类:如HashMap、LinkedList等等。如果这些容器为静态的,那么它们的生命周期与程序一致,则容器中的对象在程序结束之前将不能被释放,从而造成内存泄漏。简单而言,长生命周期的对象持有短生命周期对象的引用,尽管短生命周期的对象不再使用,但是因为长生命周期对象持有它的引用而导致不能被回收。
- 各种连接,如数据库连接、网络连接和IO连接等。在对数据库进行操作的过程中,首先需要建立与数据库的连接,当不再使用时,需要调用close方法来释放与数据库的连接。只有连接被关闭后,垃圾回收器才会回收对应的对象。否则,如果在访问数据库的过程中,对Connection、Statement或ResultSet不显性地关闭,将会造成大量的对象无法被回收,从而引起内存泄漏。
- 变量不合理的作用域。一般而言,一个变量的定义的作用范围大于其使用范围,很有可能会造成内存泄漏。另一方面,如果没有及时地把对象设置为null,很有可能导致内存泄漏的发生。
- 内部类持有外部类,如果一个外部类的实例对象的方法返回了一个内部类的实例对象,这个内部类对象被长期引用了,即使那个外部类实例对象不再被使用,但由于内部类持有外部类的实例对象,这个外部类对象将不会被垃圾回收,这也会造成内存泄露。
- 改变哈希值,当一个对象被存储进HashSet集合中以后,就不能修改这个对象中的那些参与计算哈希值的字段了,否则,对象修改后的哈希值与最初存储进HashSet集合中时的哈希值就不同了,在这种情况下,即使在contains方法使用该对象的当前引用作为的参数去HashSet集合中检索对象,也将返回找不到对象的结果,这也会导致无法从HashSet集合中单独删除当前对象,造成内存泄露。
minor gc运行的很频繁可能是什么原因引起的?
1、 产生了太多朝生夕灭的对象导致需要频繁minor gc
2、 新生代空间设置的比较小
minor gc运行的很慢有可能是什么原因引起的?
1、 新生代空间设置过大。
2、 对象引用链较长,进行可达性分析时间较长。
3、 新生代survivor区设置的比较小,清理后剩余的对象不能装进去需要移动到老年代,造成移动开销。
4、 内存分配担保失败,由minor gc转化为full gc
5、 采用的垃圾收集器效率较低,比如新生代使用serial收集器
垃圾回收的优点以及原理
优点:由于有个垃圾回收机制,Java中的对象不再有"作用域"的概念,只有对象的引用才有"作用域"。垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。
原理;垃圾回收器通常是作为一个单独的低级别的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清楚和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。回收机制有分代复制垃圾回收和标记垃圾回收,增量垃圾回收。
GC是什么,为什么要有GC?
GC算法
- 引用计数器的实现很简单,对于一个对象A,只要有任何一个对象引用了A,则A的引用计数器就加1,当引用失效时,引用计数器就减1。只要对象A的引用计数器的值为0,则对象A就不可能再被使用。
- 标记-清除算法是现代垃圾回收算法的思想基础。标记-清除算法将垃圾回收分为两个阶段:标记阶段和清除阶段。一种可行的实现是,在标记阶段,首先通过根节点,标记所有从根节点开始的可达对象。因此,未被标记的对象就是未被引用的垃圾对象。然后,在清除阶段,清除所有未被标记的对象。与标记-清除算法相比。
- 标记整理:首先通过根节点,标记所有从根节点开始的可达对象。因此,未被标记的对象就是未被引用的垃圾对象,整理阶段就是把标记的对象移动到一侧,之后清除掉其余的的未标记的,这样就解决了标记清楚造成的内存碎片化问题。
- 复制算法是一种相对高效的回收方法不适用于存活对象较多的场合如老年代将原有的内存空间分为两块,每次只使用其中一块,在垃圾回收时,将正在使用的内存中的存活对象复制到未使用的内存块中,之后,清除正在使用的内存块中的所有对象,交换两个内存的角色,完成垃圾回收。