之前学习了javaGC的原理机制,有了一定的了解,现在做一个整理总结,便于理解记忆,包括三个问题:

1. java GC是什么时候做的?

2. java GC作用的东西是什么?

3. java GC具体都做了些什么事情?

关于java GC原理参看另一篇随笔:

http://www.cnblogs.com/clarke157/p/7091990.html

1. java GC是什么时候做的?

也就是GC的触发条件,eden 满了minor gc,升到老年代的对象大于老年代剩余空间full gc,或者小于时被HandlePromotionFailure参数强制full gc;gc与非gc时间耗时超过了GCTimeRatio的限制引发OOM,调优诸如通过NewRatio控制新生代老年代比例,通过 MaxTenuringThreshold控制进入老年前生存次数等。

2. java GC作用的东西是什么?

从GC root搜索不到,而且经过第一次标记、清理后,仍然没有复活的对象。

3. java GC具体都做了些什么事情?

年轻代做的是复制清理、from survivor、to survivor是干啥用的、年老代做的是标记清理、标记清理后碎片要不要整理、复制清理和标记清理有有什么优劣势

年轻代上的内存分配是这样的,年轻代可以分为3个区域:Eden区和两个存活区(Survivor 0 、Survivor 1)。

  1. 绝大多数刚创建的对象会被分配在Eden区,其中的大多数对象很快就会消亡。Eden区是连续的内存空间,因此在其上分配内存极快;

  2. 当Eden区满的时候,执行Minor GC,将消亡的对象清理掉,并将剩余的对象复制到一个存活区Survivor0(此时,Survivor1是空白的,两个Survivor总有一个是空白的);

  3. 此后,每次Eden区满了,就执行一次Minor GC,并将剩余的对象都添加到Survivor0;

  4. 当Survivor0也满的时候,将其中仍然活着的对象直接复制到Survivor1,以后Eden区执行Minor GC后,就将剩余的对象添加Survivor1(此时,Survivor0是空白的)。

  5. 当两个存活区切换了几次(HotSpot虚拟机默认15次,用-XX:MaxTenuringThreshold控制,大于该值进入老年代)之后,仍然存活的对象(其实只有一小部分,比如,我们自己定义的对象),将被复制到老年代。

Java 也是有内存泄露的,虽然Java有著名的GC( 垃圾回收机制),由于Java是通过程序来分配内存空间,释放则交给GC, 由于程序编写不当,仍然会引起内存泄露。

Java中的内存泄露的情况:长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄露,尽管短生命周期对象已经不再需要,但是因为长生命周 期对象持有它的引用而导致不能被回收,这就是java中内存泄露的发生场景。例如在Application中保存一个对象,这个对象其实没有使用了,但是 由于一直被引用,造成不能回收。
内存泄露的情况是:一个外部类的实例对象的方法返回了一个内部类的实例对象,这个内部类对象被长期引用了,即使那个外部类实例对象不再被使用,但由于内部类持久外部类的实例对象,这个外部类对象将不会被垃圾回收。

内存泄露的另外一种情况:当一个对象被存储进HashSet集合中以后,就不能修改这个对象中的那些参与计算哈希值的字段了,否则,对象修改后的哈希值与
最初存储进HashSet集合中时的哈希值就不同了,这也会导致无法从HashSet集合中单独删除当前对象,造成内存泄露。

  1. Java内存泄露根本原因是什么呢?长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄露,尽管短生命周期对象已经不再需要,但是因为长生命周期对象持有它的引用而导致不能被回收,这就是java中内存泄露的发生场景。具体主要有如下几大类:
  2. 1、静态集合类引起内存泄露:
  3. HashMapVector等的使用最容易出现内存泄露,这些静态变量的生命周期和应用程序一致,他们所引用的所有的对象Object也不能被释放,因为他们也将一直被Vector等引用着。
  4. 例:
  5. Static Vector v = new Vector(10);
  6. for (int i = 1; i<100; i++)
  7. {
  8. Object o = new Object();
  9. v.add(o);
  10. o = null;
  11. }//
  12. 在这个例子中,循环申请Object 对象,并将所申请的对象放入一个Vector 中,如果仅仅释放引用本身(o=null),那么Vector 仍然引用该对象,所以这个对象对GC 来说是不可回收的。因此,如果对象加入到Vector 后,还必须从Vector 中删除,最简单的方法就是将Vector对象设置为null
  13. 2、当集合里面的对象属性被修改后,再调用remove()方法时不起作用。
  14. 例:
  15. public static void main(String[] args)
  16. {
  17. Set<Person> set = new HashSet<Person>();
  18. Person p1 = new Person("唐僧","pwd1",25);
  19. Person p2 = new Person("孙悟空","pwd2",26);
  20. Person p3 = new Person("猪八戒","pwd3",27);
  21. set.add(p1);
  22. set.add(p2);
  23. set.add(p3);
  24. System.out.println("总共有:"+set.size()+" 个元素!"); //结果:总共有:3 个元素!
  25. p3.setAge(2); //修改p3的年龄,此时p3元素对应的hashcode值发生改变
  26.  
  27. set.remove(p3); //此时remove不掉,造成内存泄漏
  28. set.add(p3); //重新添加,居然添加成功
  29. System.out.println("总共有:"+set.size()+" 个元素!"); //结果:总共有:4 个元素!
  30. for (Person person : set)
  31. {
  32. System.out.println(person);
  33. }
  34. }
  35. 3、监听器
  36. java 编程中,我们都需要和监听器打交道,通常一个应用当中会用到很多监听器,我们会调用一个控件的诸如addXXXListener()等方法来增加监听器,但往往在释放对象的时候却没有记住去删除这些监听器,从而增加了内存泄漏的机会。
  37. 4、各种连接
  38. 比如数据库连接(dataSourse.getConnection()),网络连接(socket)和io连接,除非其显式的调用了其close()方法将其连接关闭,否则是不会自动被GC 回收的。对于Resultset Statement 对象可以不进行显式回收,但Connection 一定要显式回收,因为Connection 在任何时候都无法自动回收,而Connection一旦回收,Resultset Statement 对象就会立即为NULL。但是如果使用连接池,情况就不一样了,除了要显式地关闭连接,还必须显式地关闭Resultset Statement 对象(关闭其中一个,另外一个也会关闭),否则就会造成大量的Statement 对象无法释放,从而引起内存泄漏。这种情况下一般都会在try里面去的连接,在finally里面释放连接。
  39. 5、内部类和外部模块等的引用
  40. 内部类的引用是比较容易遗忘的一种,而且一旦没释放可能导致一系列的后继类对象没有释放。此外程序员还要小心外部模块不经意的引用,例如程序员A 负责A 模块,调用了B 模块的一个方法如:
  41. public void registerMsg(Object b);
  42. 这种调用就要非常小心了,传入了一个对象,很可能模块B就保持了对该对象的引用,这时候就需要注意模块B 是否提供相应的操作去除引用。
  43. 6、单例模式
  44. 不正确使用单例模式是引起内存泄露的一个常见问题,单例对象在被初始化后将在JVM的整个生命周期中存在(以静态变量的方式),如果单例对象持有外部对象的引用,那么这个外部对象将不能被jvm正常回收,导致内存泄露,考虑下面的例子:
  45. class A{
  46. public A(){
  47. B.getInstance().setA(this);
  48. }
  49. ....
  50. }
  51. //B类采用单例模式
  52. class B{
  53. private A a;
  54. private static B instance=new B();
  55. public B(){}
  56. public static B getInstance(){
  57. return instance;
  58. }
  59. public void setA(A a){
  60. this.a=a;
  61. }
  62. //getter...
  63. }
  64. 显然B采用singleton模式,它持有一个A对象的引用,而这个A类的对象将不能被回收。想象下如果A是个比较复杂的对象或者集合类型会发生什么情况
  1. 对象AB互相引用,最后会不会被GC回收?
    GC里边在JVM当中是使用的ROOT算法,ROOT算法,什么称作为ROOT呢,就是说类的静态成员,静态成员就是static修饰的那种,是“根”的 一个,根还包括方法中的成员变量,只有成员或对象不挂在根上,GC的时候就可能把他们搞掉,这里提到的循环引用,就看这个循环引用是否挂在根上,如果挂在 根上,如果这个根还被JVMJava代码所执行的话,就不会GC掉,如果说这个根已经被释放掉了,这个对象不挂在跟上了,那个这个对象就会被GC掉。

java GC是何时对什么东西做什么事情的更多相关文章

  1. java GC是在什么时候,对什么东西,做了什么事情

    面试题:“你能不能谈谈,java GC是在什么时候,对什么东西,做了什么事情?” 面试题目:地球人都知道,Java有个东西叫垃圾收集器,它让创建的对象不需要像c/cpp那样delete.free掉,你 ...

  2. java GC是在什么时候,对什么东西,做了什么事情?

    1.新生代有一个Eden区和两个survivor区,首先将对象放入Eden区,如果空间不足就向其中的一个survivor区上放,如果仍然放不下就会引发一次发生在新生代的minor GC,将存活的对象放 ...

  3. Java GC 面试问题

    转自:http://icyfenix.iteye.com/blog/715301 这个帖子的背景是今晚看到je上这张贴:http://www.iteye.com/topic/715256,心血来潮写下 ...

  4. JAVA GC垃圾收集器的分析

    本篇文章主要介绍了"JAVA GC垃圾收集器的分析",主要涉及到JAVA GC垃圾收集器的分析方面的内容,对于JAVA GC垃圾收集器的分析感兴趣的同学可以参考一下.       ...

  5. [面试] Java GC (未整理完)

    Java GC简介 什么是 GC ? Java程序不用像C++程序在程序中自行处理内存的回收释放.这是因为Java在JVM虚拟机上增加了垃圾回收(GC)机制,用以在合适的时间触发垃圾回收. 你都了解哪 ...

  6. java GC jvm 内存分布 和新生代,老年代,永久代,(详细)

    如果大家想深入的了解JVM,可以读读周志明<深入理解Java虚拟机:JVM高级特性与最佳实践> 需要掌握的东西,包括以下内容.判断对象存活还是死亡的算法(引用计数算法.可达性分析算法).常 ...

  7. Java GC(垃圾回收)机制知识总结

    目录 Java GC系列 Java关键术语 Java HotSpot 虚拟机 JVM体系结构 Java堆内存 启动Java垃圾回收 Java垃圾回收过程 垃圾回收中实例的终结 对象什么时候符合垃圾回收 ...

  8. Java GC回收机制

    优秀Java程序员必须了解的GC工作原理 一个优秀的Java程序员必须了解GC的工作原理.如何优化GC的性能.如何与GC进行有限的交互,因为有一些应用程序对性能要求较高,例如嵌入式系统.实时系统等,只 ...

  9. 成为Java GC专家(3)—如何优化Java垃圾回收机制

    为什么需要优化GC 或者说的更确切一些,对于基于Java的服务,是否有必要优化GC?应该说,对于所有的基于Java的服务,并不总是需要进行GC优化,但前提是所运行的基于Java的系统,包含了如下参数或 ...

随机推荐

  1. 提示"No 'Access-Control-Allow-Origin' header"及Spring 中解决跨域问题

    问题描述 No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://12 ...

  2. spring框架-----轻量级的应用开发框架

    一.bean 1.容器实例化 ApplicationContext ac=             new ClassPathXmlApplicationContext("applicati ...

  3. hdu 1011 树形背包

    http://blog.csdn.net/libin56842/article/details/9876503 这道题和poj 1155的区别是: poj1155是边的价值,所以从边的关系入手 hdu ...

  4. linux下查看内存的使用情况

    windows上有各种软件可以进行“一键加速”之类的操作,释放掉一些内存(虽然我暂时不知道是怎么办到的,有待后续学习).而任务管理器也可以很方便地查看各进程使用的内存情况,如下图: 同样地,linux ...

  5. java 生成和解析xml

    本文主要使用的是Jdom.jar包(包的下载百度一下)实现了生成xml文件和解析xml文件 下面是生成xml的实现 说明:stuLists集合是一个存放着Student对象的集合 import jav ...

  6. perf4j 监控请求 + traceId区分日志

    1. 场景 从request进入Controller到出去的时间, 可以统计接口访问的一些数据,如:平均处理时间.最大处理时间 2. 代码 2.1 mvc-servlet 定义切面和拦截器 <? ...

  7. rocketmq 两个线程同时消费一个消息

    1.问题描述 线上项目A部署两台机器,每台机器两个实例,订阅同一个topic,消费心跳数据. (两台机器host1,host2) 运维同事 部署时 有一个实例用root账户重启的, 然后该实例出现两个 ...

  8. Angularjs ngTable使用备忘

    项目中用到angularjs的表格ng-table,功能相当强大,像搜索.排序.checkbox.分页.每页表格显示数目等都有.API,demo什么的也只能参考官网了.这里做个备忘,哪天肯定还会用到. ...

  9. Python-并发编程(进程)

    接下来我们用几天的时间说一说python中并发编程的知识 一.背景知识 顾名思义,进程即正在执行的一个过程.进程是对正在运行程序的一个抽象. 进程的概念起源于操作系统,是操作系统最核心的概念,也是操作 ...

  10. 01.php面向对象

    下面是php_oop的一些基本知识 <?php //echo "<meta charset='utf-8'>" //设置中文输出 //1.面向对象类的建立: cl ...