java学习笔记之: JVM一:内存

写在前头:看书入门, java玩了这么久了,也没仔细研究下这种重要的基础部分,最近抽空在看”深入理解java虚拟机 JVM高级特性与最佳实践“,写点学习总结;

一.内存结构
a.我们常说java内存结构=堆+栈,实际上这只是我们最常出问题的地方,我们最终要重点研究的也是这一部分
b. 虚拟机的规定呢?–>堆+栈+程序计数器,直接上图
java学习笔记之: JVM一:内存_第1张图片
栈还存放着动态链接: 运行时实时编译成实际的实现类,实现动态编译
当然 这里的方法区是存在争议的,因为不同虚拟机厂商/版本会有差异,栈也分虚拟机栈和本地方法栈,合在一块理解更容易
其中 通过存储内容可以明显看出,栈和程序计数器是线程独享的,堆是线程共享的

二.StackOverFlowError & OutOfMemoryError

三.创建对象
java学习笔记之: JVM一:内存_第2张图片
当然还有疑问啦 后续再补充
怎么去定位对象呢? –>句柄池和直接指针访问两中方法,差异就在于是否把堆中的对象的地址单独存放在句柄池(堆)中,这样垃圾回收时造成对象移动时是否去改变栈中的引用地址的值,改句柄池的值就行

四.回收对象

首先需要明确一下我们的目标   

a、java在线程中,运行了一段代码,有这么个局部变量myclass A,A的引用地址存在栈,程序走到哪存在计数器,对象A的具体内容存在堆中,线程结束了,局部变量就失效了,计数器走到最后一步了,这两部分里存到数据就直接删掉得了嘛,随线程而生随线程而灭,
并且栈帧之类的在编译期间就已经确定了,内存回收和分配都有确定型,没什么好研究的
b、但是堆里面的内容就不一定了 搞不好其他地方还在引用 –>线程共享的数据 没法简单的回收,所以我们所研究的垃圾收集器相关的东西 都是针对堆的

  1. 谁是垃圾?

    没人要了就是垃圾
    a.引用计数算法(淘汰了):引用一次就计数+1,为0就是垃圾,but无法解决循环引用的问题 如下
    Object A = B
    Object B = A

    b.可达性分析算法(GC roots算法/根节点搜索算法):
    从根节点出发找不到的就是垃圾 如上的从A找能找到B对象 B就是活的 能解决循环引用的问题,关键点在于哪些是GC roots
    java学习笔记之: JVM一:内存_第3张图片

  2. 什么时候回收

    cpu空闲的时候/堆满了 或者达到设定比例值了就GC/FULL GC
    
  3. 怎么回收

    先介绍垃圾回收算法:标记清除,复制算法,标记整理,分代(并不是单独的算法)
    算法的具体实现:
    以sun的Hotspot的实现为例

    1.Serial/SerialOld 串行收集器
    2.ParNew 并行收集器
    3.Pareller Scavenge/Pareller Old 吞吐量优先收集器
    4.CMS Concurrent Mark Sweep并发收集器(老年代)
    5.G1 垃圾优先收集器
    每种收集器年轻代/老年代组合可以得到不同效果,同时也可以设定备用收集器
    
    串行:暂停工作线程,运行一个GC线程
    并行:暂停工作线程 , 并发运行多个GC线程 只是GC线程并发而已
    并发:并发运行工作线程和GC线程  这才是我们常说的并发
    

    从线程的哪个步骤开始回收呢?

    安全点/安全区域
    

    回收的步骤呢?

    每个收集器的步骤不一样,但无外乎标记和清除
    

    java学习笔记之: JVM一:内存_第4张图片

五.内存的分配和回收策略
java学习笔记之: JVM一:内存_第5张图片
其基本策略称之为担保策略,因为GC前不确定能存活多少对象,所以Minor GC是有风险的,有可能survivor to装不下,就需要老年代做担保,但即便担保 也有可能失败,失败了就要FULL GC,如果设置HandlePromotionFailure为不允许担保失败,则直接FULL GC以防止担保失败

你可能感兴趣的:(java学习笔记,JVM)