JVM笔记

JVM笔记

  • JVM内存区域划分----6大区域
    线程私有内存 :①程序计数器 ②虚拟机栈 ③本地方法栈
    线程私有指的是这三块区域生命周期与线生命周期相同,随着线程的创建而创建,随着线程的销毁而回收,不同线程间则三块内存彼此隔离。
    1. 程序计数器
    当前线程正在执行的字节码行号指示器,唯一一个不会产生OOM(OutOfMeoryError)异常的区域
    若执行执行的时native方法,计数器为0
    2. 虚拟机栈-java方法的内存模型(-Xss设置栈的大小)
    每个方法执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口的信息,每一个方法从调用直至执行完成的过程,对应
    一个栈帧在虚拟机中入栈和出栈的过程,声明周期与线程相同
    每个方法从调用到执行完成的过程,就对应一个栈帧在JVM中入栈与出栈过程
    一共产生两种异常,StackOverflowError和OOM
    3. 本地方法栈-native方法的内存模型
    HotSpot:本地方法栈与虚拟机栈合二为一。
    线程共享内存
    线程共享是所有线程共享此三块区域内存,彼此不隔离
    4. java堆(GC堆,垃圾回收的主要负责区域)
    javaHeap是jvm管理的最大的内存区域
    存放所有对象实例以及数组空间
    -Xmx设置堆的最大值
    -Xms设置堆的最
    5. 方法区
    用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据。在jdk1.8以前的HotSpot虚拟机中,方法与也被成为永久代(JDK8已被元空间取代)
    6. 运行时常量池
    是方法区的一部分,存放字面量与符号引用
    字面量:指的是直接写出来的值: 10 “string”
    符号引用:
    OOM产生的原因:
    内存泄漏:产生的对象永远无法被垃圾回收
    内存溢出:当前堆的空间过小,没有足够容纳新的对象,适当的将堆的大小扩大就可以解决此问题

  • 垃圾回收策略(主要在堆和方法区)
    判断对象存活?
    ①:引用计数法:给每个对象附加一个引用计数器,每当有一个引用指向当前对象,计数器+1,每当有引用不在指向当前对象计数器值-1,
    引用计数器值为0的对象就被标记为不在存活
    缺点: 无法解决循环引用的问题(你中有我,我中有你)
    ②:可达性分析算法:
    通过一系列称为"GC Roots"的对象作为起始点,从这些结点开始向下搜索,搜索走过的路径称之为"引用链", 当一个对象到GCRoots没有任何
    引用链相连时(不可达),证明此对象时不可用的
    哪些对象可以作为GC Roots:
    虚拟机栈与本地方法栈中的临时变量指向的对象,
    类中静态变量引用的对象
    类中常量引用的对象

    JDK1.2之后关于引用的扩充:
    强度依次递减为:
    强引用、 程序中普遍存在的,GCRoots对象指向的引用都属于强引用,只要当前对象被任意一个强引用指向,即便内存不够用也不能回收此对象
    软引用、 用来描述有用但是不必须的对象(缓存对象)当前系统内存够用时,仅被软引用指向的对象还存活;若内存不足时,则下次GC时,会将所有仅被软引用指向的对象进行GC
    JDK1.2:SoftReference类来表示软引用
    弱引用、 也是用来描述非必须对象,但是强度要弱于软引用,仅被弱引用指向的对象,只能存活到下次GC之前,当GC开始时,不管内存是否够用,都会回收仅被弱引用指向的对象
    JDK1.2:WeakReference类,来表示弱引用
    虚引用、 是四大引用中最弱的一种引用关系。虚引用完全对对象的生存周期不造成任何影响,并且无法通过虚引用取得一个对
    为一个对象设置虚引用的唯一目的就在于该对象被GC之前由系统发回回收通知
    JDK1.2:PhantomReference类表示虚引用

  • 当一个对象到GC Roots不可达,就一定会当场去世吗?(finalize() 对象自我拯救)
    JVM在进行GC之前,需要判断即将回收的对象所在的类是否重写了finalize()
    若没有重写,此对象直接被回收
    若对象所在的类重写了finalize()
    1. 若finalize()未被调用,会调用finalize(),若对象在此次调用过程中与GCRoots有路可达,此对象不在被回收
    2. 若finalize()已被JVM调用,此对象直接被回收。

  • 已经死亡的对象如何进行垃圾回收
    方法区回收(永久代回收)(方法区的GC频率非常低)
    堆上的垃圾回收算法:
    1. 标记清除算法
    算法分为标记和清除两个阶段:
    a. 标记阶段首先将需要回收的对象打上标回收记
    b. 清除阶段一次性回收所有被打上标记的对象空间
    最大缺点:
    标记会产生大量不连续空间碎片,导致GC频发发生
    2. 复制算法(新生代垃圾回收算法)
    堆(所有对象和数组对象)
    新生代:大部分对象先在新生代产生,大部分对象在此区域存放,该区域特点“对象朝生夕死”(存活率低)
    老年代:存活率高。
    方法原理: 它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块,当这块内存需要进行垃圾回收时,会将此区域还存活的对象复制到另一块上面
    ,然后再把已经使用过的内存区域一次清理掉。
    优点:每次都是对整个半区进行内存回收,内存分配时也就不需要考虑内存碎片等复杂情况,只需要一定顶的指针,按顺序分配即可,实现简单
    运行高效
    java中的复制算法(新生代垃圾回收算法)
    将新生代内存分为一块较大的Eden(伊甸园)与两块大小相等的Survivor(幸存者),默认比例
    8 : 1 : 1,每次使用Eden与其中一块Survivor区域(一个叫From区,另一个叫To区)
    核心流程:
    1. 对象默认都在Eden区产生,当Eden空间即将满时,触发一次MinorGC(新生代GC),将Eden区所有存活对象复制到From区,
    然后一次性清理掉Eden区的所有空间
    2. 当Eden区再次即将满时,触发MinorGC,此时需要将Eden与from区的所有存活对象复制到TO区,然后在一次清理掉Eden与from的
    所有空间。之后的新生代GC重复阶段2(只是From和TO区来回作为备用区域)
    备注:某些对象来回在From和To区交换若干次(默认15)以上,将其置入老年代空间
    3. 标记整理算法(老年代的垃圾回收算法Full GC)
    核心思想相较于标记清除-整理阶段让先存活的对象向一端移动,而后清理掉存活对象边界之外的所有空间
    为何老年代不采用复制算法?
    由于老年代中的对象存活率高,复制的对象较多
    4. 分代收集策略(javaGC)
    将堆空间分为新生代(-Xmn)与老年代空间,其中新生代采用复制算法,老年代采用标记整理算法

  • JVM内置的检测工具

    1. jps: 返回当前操作系统中所有JVM进程ID jps -l(输出包名.类名)
    2. jmap: 查看单签JVM的内存情况 jmap -heap PID (查看PID的JVM的堆情况)
    3. jstack: 查看当前JVM的线程栈情况,常用于解决线程卡死问题
  • java内存模型(描述并发程序的逻辑模型)
    java的内存模型主要定义JVM如何将变量存储到内存中,又如何将内存中的变量取回等细节。
    变量(线程共享):类中的实例属性,静态属性以及数组元素
    1. 所有变量必须存储在主内存中
    2. 每个线程的内存叫工作内存,工作内存中保存了使用主内存的变量的副本。
    3. 线程对于变量的所有操作必须在工作内存中进行,而不能直接操作主内存,不同线程间也无法访问彼此的工作内存,变量间的值传递均通过主内存来进行

  • java内存的三大特性:
    并发程序同时满足一下三个线程才是线程安全的,任意一个不满足都不是线程安全
    原子性: 一个或一组操作要么全部发生,要么全都不发生,基本数据类型的访问读写属于原子性操作,如需要更大范围的原子性操作(运算等),需要使用synchronized
    或Lock来保证原子性
    可见性: 当一个线程修改了共享变量的值,其他线程都能够立即得知此修改
    synchronized/final/volatile可以保证可见性
    有序性:happens-before(先行发生原则,JVM层面保证的有序性)

  • volatile变量的特殊规则:

    1. volatile变量具备可见性,当一个线程修改了这个变量的值,其他线程能够立即得知此修改
      应用场景:
      a. 运算结果不依赖当前变量的值(没有自增自减等非原子性操作)
      b. 变量不需要与其他变量共同参与运算(eg : int j = i + 1)
    2. 使用volatile变量可以禁止cpu进行指令安排。(双重加锁单例模式)
      a. 当程序执行到volatile的读或写时,在其前面的操作一定全部进行完毕,并且结果对后面操作可见,后面的操作也还没有发生
      b. 指令重排时,不能将volatile的语句提前后滞后。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值