• JVM 小总结


    JVM

    • 1、JVM 的位置

      • 运行在操作系统之上的
      • java程序是排在 jre(jvm) 上的
      • 1597471022105
      • 1597471402390
      • 1597471485960
      • 所谓的JVM 调优就是在堆里面调,方法区就是 一个特殊的堆
    • 2、JVM 的体系结构

    • 3、类的加载器

      • 作用
        • 加载 class 文件
        • 1597472487894
        • 类加载器分为好几个,有等级
          • 1、虚拟机自带的加载器
          • 2、启动类(根)加载器
          • 3、扩展类加载器
          • 4、应用程序(系统类)加载器
    • 4、双亲委派机制

      • 当某个类加载器需要加载 .class 文件时,它首先把这个任务委托给他们的上级类加载器,递归这个操作,如果上级的类加载器没有加载,自己才会加载这个类

      • 作用:
        • 1、防止重复加载同一个 .class。通过委托去向上面问一问,加载过了,就不用再加载一遍。保证数据安全
        • 2、保证核心 .class 不能被篡改,通过委托方式,不会去篡改核心 .class 。即使篡改也不会去加载,即使加载也不会是同一个 .class 对象了,不同的加载器加载同一个 .class 也不是同一个 Class 对象,这样保证了 Class 执行安全。
      • 1597494745829

      • 类加载的过程和使用那个加载器
        • 1、类加载器收到类加载的请求
        • 2、将这个请求向上委托给父类加载器去完成。一直向上委托,直到启动类加载器
        • 3、启动类加载器检查是否能够加载当前这个类,能加载就结束,使用当前的类加载器,否则,跑出异常,通知子加载器进行加载
    • 5、沙箱安全机制

    • 6、Native

      • JNI (本地方法接口) java native interface

        • // native :

          ​ 1、凡是带了 native 关键字的,说明 java 的作用范围达不到了,会去调用底层 C 语言的库

          2、会进入本地方法栈,调用 JNI, 调用本地方法库,

          ​ JNI 的作用就是扩展 java 的使用,融合不同的语言为 java 所用,最初是 C、C++

          所以在内存中开辟了一块区域,为了登记 native 方法,

          3、调用其他接口其实还可以使用 Socket、WebService、http、rpc 、restful

    • 7、PC 寄存器

      • 程序计数器:Program Counter Register
      • 每个线程都有一个程序计数器,就是一个指针,指向方法区中的字节码(用来存储存储指向像一条指令的地址,也即将要执行的指令代码),在执行引擎读取下一条指令, 是一个非常小的内存空间,几乎可以忽略不计
    • 8、方法区

      • Method Area:

        • 方法区是被所有的线程共享,所有字段和方法字节码,以及一些特殊方法,如构造函数,接口代码也在此定义,简单说,所有定义的方法的信息都保存在该区域,此区域属于共享区间,

          • 静态变量、常量、类信息(构造方法、接口定义),运行时的常量存在方法区中,但是实例变量存在堆内存中,和方法区无关

            说白了就是:

            ​ staic、 final、Class、常量池、、、

    • 9、栈

      • 数据结构。栈和队列进行比较

      • 栈:先进后出,后进先出

        • 所以为什么 main 方法最后退出?

          • 栈溢出、递归问题(死循环)、无限压栈 、压栈超过了栈的深度

          • 1597582643769

          • 栈:
            • 何时发生栈内存溢出?
              • 对于一台服务器而言,每一个用户请求,都会产生一个线程来处理这个请求,每一个线程对应着一个栈、栈会分配内存,此时如果请求过多,这时候内存就不够了,就会发生内存溢出
            • 什么时候会发生栈溢出 ?
            • 栈溢出是指不断的调用方法,不断的压栈,最终超出了栈允许的栈的深度,最终超出了栈允许的栈深度,就会发生栈溢出,比如递归操作没有终止,死循环

          • 帮助记忆:
            • 可以把内存你做一个大箱子,栈比作一个小箱子,栈溢出是指小箱子装不下了,而栈内存溢出是大箱子在也装不下小箱子了
          • 主管程序的运行,生命周期和线程同步

          • 线程结束,栈内存你就会释放

          • 对于栈来说,没有垃圾回收的问题

          • 栈里面放的东西:

            • 8 大基本类型+ 对象引用 + 实例的方法
          • 栈运行原理:
          • 栈、堆、方法区的交互关系
            • 栈是类模板,堆是对象实例
      • 队列: 先进先出 (FIFO)

    • 10、三种 JVM

      • Sun 公司 HotSpot
      • IBM J9VM
      • BEA JRockit
    • 11、堆

    • 堆的图
    • 1597634059851

      • 1597633958147
        • 逻辑上存在,物理空间上不一定存在
      • heap、一个 jvm 只有一个堆内存,对内存的大小是可以调节的
    • 12、新生区(伊甸园区)、老年区 、幸存区0, 幸存区1

      • 新生区是类诞生和成长的地方,甚至死亡
      • 多有的对象都是在一点园区new出来的
    • 1597630172545

      • GC 垃圾回收,主要是在伊甸园区和老年区

      • 假设内存满了、OOM、java.lang.OutOfMemoryError: java heap space
      • 无限字符串的例子 - 其实也就是无限 new 对象:

        • 1597632195015

        • VM 参数调试
        • 1597635291658

        • 1597632866278

    • 13、永久区

    • 这个区域常驻内存的,用来存放 jdk 自身携带的 Class 对象,Interface 元数据,存储的是 java 运行时的一些环境或类信息,这个区域不存在垃圾回收,关闭虚拟机就会释放这个区域的内存

    • 什么情况下在永久区就崩了呢?
      • 一个启动类加载了大量的第三方 jar 包,tomcat 部署了太多的应用,或者大量动态生成的反射类,不断的被加载,直到内存满了,就出现 OOM
      • jdk1.6之前: 叫永久代,常量池是在方法区

      • jdk1.7: 永久带,但是慢慢的退化了,去永久代,常量池在堆中

      • jdk1.8之后:无永久代,常量池在元空间

      • 在一个项目中,突然出现 OOM 故障,那么该如何排除 - 研究为什么出错?

        • 能够看到代码第几行出错:

          • 内存快照分析工具,MAT、Jprofiler

          • debug: 只能一行行的分析代码

          • MAT、Jprofiler作用

            • 分析 Dump、内存文件,快速定位内存泄漏
            • 获得对中的数据
            • 获得大的对象
    • 14、对内存调优

    • 15、GC (自动垃圾回收机制)

      • 1597652866809

      • Jvm 在进行 GC 时,并不是对以下三个区域统一回收,大部分时候,回收都是新生代,

        • 新生代
        • 辛存区( from to)
        • 老年区
          • GC 两种类型: 轻GC(普通 GC), 重 GC (全局 GC)
      • GC 的题目 :

        • 1、JVM 的内存模型和分区 - 详细到每个区放什么?

          • 方法区
          • 本地方法栈
          • PC 计数器
        • 2、堆里面的分区有哪些?

          • 新生区(伊甸园)
          • 幸存区(from to),谁空谁是 to
          • 老年区
        • 3、GC 的算法有哪些?

          • 标记清除法
          • 标记压缩
          • 复制算法
          • 引用计数器
        • 4、轻 GC 和 重 GC 分别在什么时候发生?

      • 常用算法
        • 1597654086722
    • 16、JMM

      • 1、什么是 JMM?
        • Java Memory model Java 内存模型
      • 2、干嘛的?
        • 作用:缓存一致性协议,用于定义数据读写的规则(遵守,找到这个规则)

        • JMM 定义了线程的主内存之间的抽象关系:线程之间的共享变量存储在主内存(Main Memory)中,每个线程都有一个私有的本地内存(Local Memory)

        • 1597673534829

        • CPU 中运行的线程从主存中拷贝共享对象 obj 到它的 CPU 缓存,把对象 obj 的 count 变量改为 2,但每个变量对运行在右边 CPU 中的线程不可见,因为这个更改还没有 flush 到主存中,要解决共享对象可见性这个问题,我们可以用 java volilate 关键字或者加锁

        • 1597673829700

        • 解决共享对象可见性这个问题: volilate
      • 3、如何学习?

        • ​ JMM: 抽象的概念 - 理论

        • 1597674717710


    • 17、总结

      • 内存效率:

        • 效率最高: 复制算法 > 标记清除算法 > 标记压缩算法
        • 内存整齐度: 复制算法 = 标记压缩算法 > 标记清除算法
        • 内存利用率: 标记压缩算法 = 标记清除算法 > 赋值算法
      • 思考一下, 难道没有最优的算法吗?

        • 没有,没有最好的算法,只有最合适的算法 --->

        • 分代收集算法
          • 每一代都有不同的算法

          • 年轻代:

            • 存活率低
            • 复制算法
          • 老年代:

            • 区域大: 存活率

            • 标记清除(内存碎片不是太多) + 标记压缩混合 实现

  • 相关阅读:
    无法将类型为“xxxx”的对象强制转换为类型“Microsoft.SharePoint.WebPartPages.WebPart”。
    [win32 api] FindWindow FindWindowEx EnumChildWindows
    WPF线程中被修改后DataGrid数据不能及时更新的问题
    Android Adapter 与 Listview
    LINQ 查询操作及进行数据转换
    匿名方法lambda表达式
    WPF知识4 依赖属性
    LINQ 入门
    WPF绑定.NET对象(二)Visifire的数据绑定
    LINQ 查询操作中的类型关系
  • 原文地址:https://www.cnblogs.com/jcjc/p/13520585.html
Copyright © 2020-2023  润新知