JVM探究

简介: 请你谈谈JVM的理解?java8虚拟机和之前的变化有哪些?

JVM探究

  • 请你谈谈JVM的理解?java8虚拟机和之前的变化有哪些?
  • 什么是OOM,什么是栈内存溢出StackOverFlowError?
  • JVM常用的调优参数有哪些?
  • 内存快照如何抓取,怎么分析Dump文件?
  • 谈谈JVM中,类加载器你的认识?

    JVM的位置?

    1. JVM的体系结构

    2. 类加载器

    3. 双亲委派机制

      Java是运行在Java的虚拟机(JVM)中的,但是它是如何运行在JVM中了呢?我们在IDE中编写的Java源代码被编译器编译成.class的字节码文件。然后由我们得ClassLoader负责将这些class文件给加载到JVM中去执行。

      JVM中提供了三层的ClassLoader:

      1. Bootstrap classLoader:主要负责加载核心的类库(java.lang.*等),构造ExtClassLoader和APPClassLoader。
      2. ExtClassLoader:主要负责加载jre/lib/ext目录下的一些扩展的jar。
      3. AppClassLoader:主要负责加载应用程序的主函数类

        双亲委派机制原理:

        当一个.Class的文件被加载时,用户自定义的加载器不会先加载,首先会在AppClassLoader检查是否被加载过,如果有就无需加载了,如果没有就会拿到父类的加载器。然后调用父类的ClassLoader方法,父类同理也会检查自己是否被加载过,如果没有继续往上,这是一个递归的过程,直到达到了 Bootstrap ClassLoader之前都会检查自己是否加载过,而不是去加载。直到Bootstrap已经没有父加载器了,这时候才会考虑自己能否加载,如果自己没法加载则会下沉到子加载器去加载,一直到最底层,如果没有任何加载器能加载,则会爆出ClassNotFoundExeption

        为什么要设计这种机制呢?

        这样设计的好处就是,如果有人想替换系统级别的类,系统级别的类已经被BootstarpClassLoader加载过了。从一定程度上防止了危险代码的植入。

    4. 沙箱安全机制
    5. Native

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

      调用本地方法接口 JNI :java native interface

      JNI的作用:扩展java的使用,融合不同的编程语言,为java所用。最初是为了融合:C 和C++

      Java诞生的时候,C和C++很流行,必须要可以调用C和C++的程序

      它在内存区域中,专门区分出来了一块 标记区域, 本地方法栈

      它会在最终执行的时候,通过JNI加载本地方法。
      调用其他语言的接口。

    6. PC寄存器: Program Counter Register

      ​ 每个线程都有一个程序计数器,是线程私有的,就是一个指针,指向方法区中的方法字节码文件,在执行引擎读取下一条指令,是一个非常小的内存空间,几乎可以忽略不计。

    7. 方法区

      1. 方法区是被所有线程共享的,所有字段和字节码文件,以及一些特殊的方法,如构造函数,接口代码也在此定义,所有定义的信息都保存在此区域,此区域属于共享区间
      2. 方法区中都有哪些:静态变量(static )常量(final) 类信息(Class)常量池
    8. 栈:数据结构:

      程序=数据结构+算法

      栈:先进后出,后进先出。砌墙的砖头,后来居上。

      队列(FIFO):先进先出,相当于通道。消息队列

      栈:栈内存。主管程序的运行,声明周期和线程同步。

      线程结束,栈内存就会释放了,对于栈来说,不存在垃圾回收问题

      栈里面有什么?:8大基本类型、对象引用、实例的方法、

      栈的运行原理:

      栈+堆+方法区:交互关系

    9. 三种JVM

    10. 堆(Heap)

      1. 一个JVM只有一个堆内存。堆的大小是可以手动调节的。
      2. 类加载器读取了类文件后,会把什么东西放在堆中。类具体的实例+常量+方法变量。会保存我们引用类型的真实对象实例。
      3. 堆内存中,分为三个区域:新生区(伊甸园区)Yound/New、养老区 Old、永久区
      4. GC垃圾回收,主要在新生区和养老区
      5. 假设内存满了,堆内存不够,OOM,
      6. 在JDK8之后,永久储存区改了个名字:元空间。

        新生区:

        • 类:诞生和成长,甚至死亡的地方!
        • 伊甸园区:所有的对象最初创建,是在伊甸园区。
        • 幸存者区

          • 0区
          • 1区

        老年区:

        永久区:

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

        在永久区出现OOM错误:一个启动类,加载了大量的第三方jar包。大量动态生成的反射类。

        • 1.6之前:永久代,常量池是在方法区
        • 1.7“:永久代,常量池在堆中
        • 1.8之后:无永久代,常量池在元空间。

        经过研究,有99%的对象,是临时对象。

        元空间:逻辑上存在,物理上不存在。

        ## 堆内存调优

        在一个项目中,如果出现OOM故障,该如何拍错?研究为什么出错

        • 能够看到那行代码出错:内存快照分析工具,MAT,Jprofiler
        • Debug 代码一行一行分析。

          MAT,Jprofiler的作用:

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

            设置堆内存,初始化内存以及最大内存,以及当出现DumpOnOutOfMemoryError错误时:

            -Xms1m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError

            -Xms1m:初始化内存大小

            -Xmx8m:最大内存

            -XX:+HeapDumpOnOutOfMemoryError 当出现错误时Dump下来内存文件。栈溢出

            -XX:+PrintGCDetails 打印GC垃圾回收信息。

    11. 堆内存调优
    12. GC:垃圾回收

      1. JVM在进行GC的时候,并不是对这三个区域统一回收。大部分的时候都是在新生区,也就是伊甸区

        1. 新生区(伊甸区)
        2. 幸存区
        3. 老年区

          GC分为两种:轻量级G7,重量GC(全局GC)

        GC题目:

        • JVM内存模型和分区,详细到每个区都放什么?
        • 堆里面的分区有哪些?说说他们的特点
        • GC算法有哪些?标记清除法、标记整理、复制算法、引用计数器
        • 轻GC和重GC分别发生在什么时候?

        ### 引用计数法:

      ## 复制算法:

      1. 每次GC,都会将Eden活着的对象移到幸存区,一旦Eden区被GC后,就会是空的。
      2. 幸存区to和幸存区from之间的转换,那个里面是空的那个就是to,
      3. Eden和幸存区之前的转换是用的复制算法,将剩下活着的对象,复制到其他区域,然后清空该区域的对象。
      4. 当一个对象经历了 15次GC后,都还没有死,就会进入到老年区。可以通过参数设置 这个参数,来设定进去老年区的时间。

    这种算法的好处是:没有内存碎片

    坏处是:浪费了内存空间,多了一半的内存永远是空的,

    想要复制算法最佳使用场景,对象存活度较低的时候。也就是新生区

    标记算法

    1. 对活着的对象进行标记,扫描整个空间,对没有标记的对象进行清除。

      缺点:两次扫描 严重浪费时间。会产生内存碎片

      优点:不需要额外的内存空间。

    标记压缩

    对标记清除的再优化:防止内存碎片的产生,再次扫描,向一端移动存活的对象。多了一个移动成本。

总结

  1. 内存效率(时间复杂度):复制算法>标记清除算法>标记清除压缩算法
  2. 内存整齐度:复制算法=标记清除算法>标记清除压缩算法
  3. 内存利用率:标记清除算法=标记清除压缩算法>复制算法

思考一个问题,难道就没有最优的解决办法了吗?

答案就是没有,没有最好的算法,只有最合适的算法,------->GC:分代收集算法

年轻代:

  • 特点是:存活率低,极易被GC回收。
  • 所以使用复制算法

老年代:

  • 区域大:存活率高
  • 所以使用标记清除算法+标记压缩算法混合实现。

必须要深入的研究《深入理解JVM》这一本书。

JMM:Java Memory Model--------------java内存模型

  1. 什么是JMM?
  2. 它是干嘛的?

    ​ 作用:缓存一致性协议,用于定义数据读写的规则,我们必须遵守这个规则,

    ​ JMM定义了线程工作内存和主内存之间的抽象关系,线程之间的共享变量存储在主内存中,每个线程都有一个私有的本地内存。

  3. 它如何学习
相关文章
|
4月前
|
存储 算法 Java
Java面试题:深入探究Java内存模型与垃圾回收机制,解释JVM中堆内存和栈内存的主要区别,谈谈对Java垃圾回收机制的理解,Java中的内存泄漏及其产生原因,如何检测和解决内存泄漏问题
Java面试题:深入探究Java内存模型与垃圾回收机制,解释JVM中堆内存和栈内存的主要区别,谈谈对Java垃圾回收机制的理解,Java中的内存泄漏及其产生原因,如何检测和解决内存泄漏问题
61 0
|
存储 Java
探究 Java JVM 老年代:垃圾回收、内存管理与性能优化
在 Java 虚拟机(JVM)内存管理中,老年代是一个关键的部分,用于存储较长时间存活的对象。了解老年代的垃圾回收策略、内存管理方式以及性能优化方法,对于构建高性能、稳定的 Java 应用至关重要。本文将深入探讨老年代的原理、垃圾回收策略和性能优化,助您更好地掌握 JVM 内存管理。
|
Oracle JavaScript Cloud Native
【JVM深层系列】「云原生时代的Java虚拟机」针对于GraalVM的技术知识脉络的重塑和探究
【JVM深层系列】「云原生时代的Java虚拟机」针对于GraalVM的技术知识脉络的重塑和探究
347 1
【JVM深层系列】「云原生时代的Java虚拟机」针对于GraalVM的技术知识脉络的重塑和探究
|
算法 安全 Java
【JVM性能优化】CMS回收器的Full-GC流程分析以及问题探究
【JVM性能优化】CMS回收器的Full-GC流程分析以及问题探究
774 0
【JVM性能优化】CMS回收器的Full-GC流程分析以及问题探究
|
存储 安全 Java
从 JVM 中深入探究 Synchronized
Synchronized,Java 友好的提供了的一个关键字,它让开发者可以快速的实现同步。它就像一个星星,远远看去就是一个小小的点。但是走近一看,却是一个庞大的蛋糕。而这篇文章就是要将这个巨大的蛋糕切开,吃进肚子里面去。
|
存储 算法 安全
JVM探究
请谈谈你对JVM的理解? java8虚拟机和之前的变化更新? - 什么是OOM,什么是栈溢出StackOverFlowError? 怎么分析? - JVM的常用调优参数有哪些? - 内存快照如何抓取,怎么分析Dump文件? - 谈谈JVM中,类加载器你的认识
121 0
|
存储 缓存 算法
|
存储 缓存 安全
【JVM进阶之路】三:探究虚拟机对象
【JVM进阶之路】三:探究虚拟机对象
117 0
【JVM进阶之路】三:探究虚拟机对象
|
Arthas 编解码 前端开发
探究retransformClasses致使JVM Metaspace OOM的问题
### 前言 本文深入分析Arthas 3.3.0~3.4.1版本trace大方法可能导致JVM Metaspace OOM的问题。通过分析trace命令生成的增强字节码及调试分析JVM retransformClasses的处理过程,找出发生Metaspace OOM的原因,然后给出解决办法。 ### 问题说明 构造了一个测试的大方法`demo.BigMethod250.test(
1491 0
探究retransformClasses致使JVM Metaspace OOM的问题
|
16天前
|
存储 安全 Java
jvm 锁的 膨胀过程?锁内存怎么变化的
【10月更文挑战第3天】在Java虚拟机(JVM)中,`synchronized`关键字用于实现同步,确保多个线程在访问共享资源时的一致性和线程安全。JVM对`synchronized`进行了优化,以适应不同的竞争场景,这种优化主要体现在锁的膨胀过程,即从偏向锁到轻量级锁,再到重量级锁的转变。下面我们将详细介绍这一过程以及锁在内存中的变化。
29 4