《深入理解JAVA虚拟机》第三章

来源:互联网 发布:亚洲蹲 知乎 编辑:程序博客网 时间:2024/05/29 21:28

这种做的读书笔记,既不是我原创的,也不是我转载的,这种分类就很尴尬了。
内存溢出:
内存泄露:

3.1 概述
  1. Lisp是第一门真正使用内存动态分配和垃圾收集技术的语言。
  2. 程序计数器、本地方法栈、虚拟机栈这几个区域的内存分配和回收具备确定性
  3. java堆和方法区则不一样,同一个接口的不同实现类所需要 内存可能不一样;一个方法中多个分支需要的内存也可能不一样;可能只有在程序运行时才能知道某些对象的创建,这部分的内存分配和回收都是动态的。

3.2 对象已死吗
  1. 堆中放着java世界*几乎所有的*对象实例。(提问:还有哪些没有放在里面?)

 3.2.1 引用计数算法
  1. 引用计数实现简单:给定一个引用计数器,当某对象被引用时,计数器+1,当引用失效时则计数器-1 。当计数器为0时则该对象则不可能被引用。
  2. 应用案例:微软的COM技术、Python语言、游戏脚本Squirrel、FlashPlayer。
  3. 但JAVA没有使用主要是因为它不能解决对象之间的相互循环引用问题。(提问:这是个什么问题?)

 3.2.2 可达性分析算法
  1. 主流的商用程序语言(java、c#等)都是通过可达性算法来判定对象是否存活。
  2. 可达性算法就是从“GC Roots”开始,向下搜索,走过的路径叫做引用链。若某对象没有从”GC Roots”可到达的引用链,则该对象是不可用的。
  3. 可作为GC Roots的对象包括:
    虚拟机栈中引用的对象
    方法区中类静态属性引用的对象
    方法区中常量引用的对象
    本地方法栈中JNI引用的对象(提问:JNI是啥?)

(提问:这些root方式选择的先后次序?以怎样的方式选择?选择后是否会再次改变?)

 3.2.3 再谈引用
  JDK1.2之后对引用的概念进行了扩充,又将引用的类型分为以下四种:
    1.强引用 。只要强引用还在,对象就永远不会被回收,类似于“Object o= new Object();”
    2. 软引用。并不属于非必须对象,当系统将要发生内存溢出异常之前,将该部分对象列入回收范围进行二次回收,若回收后还是内存不够,则出现内存溢出异常。
    3. 弱引用。属于非必须对象,它所关联的对象只能生存到下一次回收发生之前。当垃圾收集器工作时,无论当时内存是否充足,都将回收该部分对象。
    4. 虚引用。不会对关联对象的生存时间产生影响,唯一目的是在该对象被回收时会收到一个系统通知。

 3.2.4 生存还是死亡
  1. 当某个对象被分析可达性算法标记为不可达对象时也不是“非死不可”。真正宣告一个对象的死亡是有两次标记。
    1)一个对象A标记为不可达。
    2)若A有以下两种情况则没有“拯救机会”,否则进入F-Queue队列中等待执行finalize()方法。
      (1)已经执行过finalize()方法。
      (2)没有覆盖finalize()方法。
    3)进入F-Queue的对象,稍后由一个虚拟机自动创建的、低优先级的Finalizer线程去执行finalize()方法。这里的“执行”指会触发但是不一定会等它结束。如果A能够在finalize方法中拯救自己,即重新与引用链上的任何对象建立关联,则A会被移除“即将回收”集合。

  2. 不建议使用finalize()方法。

 3.2.5 回收方法区
  1. 永久代垃圾回收的两部分:废弃常量、无用的类
  2. 认定“无用类”的三个条件:
    1)该类所有实例都被回收
    2)加载该类的ClassLoader已被回收
    3)该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。
  3. “无用类”是否被回收HotSpot虚拟机提供了-Xnoclassgc参数进行控制。还可以使用-verbose:class 、 -XX:+TraceClassLoading 、 -XX:+TraceClassLoading查看类加载和卸载信息。

(提问:反射、动态代理、ClassLoader)

0 0
原创粉丝点击