关于JVM的常见问题

1. JVM是什么?JVM的基本结构?

虚拟机,一种能够运行java字节码的虚拟机。

  • 类加载子系统: 加载 .class 文件到内存。Classload
  • 内存结构: 运行时的数据区。
  • 执行引擎: 执行内存中的.class,输出执行结果(包含GC:垃圾收集器)。
  • 本地方法的接口: 本地方法库。
    在这里插入图片描述

2.JVM内存结构

JDK1.7
在这里插入图片描述
程序计数器
就是一个指针,指向方法区中的方法字节码(用来存储指向下一个指令的地址,也即将要执行的指令代码),由执行引擎读取下一条指令,是一个非常小的内存空间,几乎可以忽略不计。
Java虚拟机栈
Java线程执行方法的内存模型,一个线程对应一个栈,每个方法在执行的同时都会创建一个栈帧(用于存储局部变量表,操作数栈,动态链接,方法出口等信息)不存在垃圾回收问题,只要线程一结束该栈就释放,生命周期和线程一致。
本地方法栈
和栈作用很相似,区别不过是Java栈为JVM执行Java方法服务,而本地方法栈为JVM执行native方法服务。登记native方法,在Execution Engine执行时加载本地方法库。

Java虚拟机管理的最大的一块内存区域,Java堆是线程共享的,用于存放对象实例。也就是说对象的出生和回收都是在这个区域进行的。
方法区
线程共享,用于存储已经被虚拟机加载的类信息、常量、静态变量等数据。
JDK1.8
在这里插入图片描述
JDK1.8与1.7最大的区别是在1.8中方法区是由元空间(元数据区)来实现。常量池移到堆中。

3. 类的加载, 类加载器的种类, 类加载机制

类加载
在这里插入图片描述
1. 加载
将.class文件从磁盘读到内存。
2.连接

  1. 验证: 验证字节码文件的正确性。
  2. 准备: 给类的静态变量分配内存,并赋予默认值。
  3. 解析: 类装载器装入类所引用的其它所有类。

3.初始化
为类的静态变量赋予正确的初始值,上述的准备阶段为静态变量赋予的是虚拟机默认的初始值,此处赋予的才是程序编写者为变量分配的真正的初始值,执行静态代码块。
4.使用
5.卸载

类加载器的种类

1. 启动类加载器(Bootstrap ClassLoader)
负责加载JRE的核心类库,如JRE目标下的rt.jar,charsets.jar等。
2. 扩展类加载器(Extension ClassLoader)
负责加载JRE扩展目录ext中jar类包。
3. 系统类加载器(Application ClassLoader)
负责加载ClassPath路径下的类包。
4. 用户自定义加载器(User ClassLoader)
负责加载用户自定义路径下的类包。

类加载机制

全盘负责委托机制
当A类中引用B类,那么除非特别指定B类的类加载器,否则就直接使用加载A类的类加载器加载B类。
双亲委派机制
指先委托父类加载器寻找目标类,在找不到的情况下再在自己的路径中查找并载入目标类。

4.什么是GC?

内存空间是有限的,那么在程序运行时如何及时的把不再使用的对象清除将内存释放出来,这就是GC要做的事。

  • GC的区域在哪里?
    JVM中,程序计数器、虚拟机栈、本地方法栈都是随线程而生随线程而灭,栈帧随着方法的进入和退出做入栈和出栈操作,实现了自动的内存清理。因此,我们的内存垃圾回收主要集中于 Java 堆和方法区中,在程序运行期间,这部分内存的分配和使用都是动态的。
  • GC的操作对象是什么?
    需要进行回收的对象就是已经没有存活的对象,判断一个对象是否存活常用的有两种办法:引用计数和可达分析。
  • 引用计数
    每个对象有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1,计数为0时可以回收。此方法简单,无法解决对象相互循环引用的问题。
  • 可达性分析(Reachability Analysis):
    从GC Roots开始向下搜索,搜索所走过的路径称为引用链。当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。不可达对象。

在Java语言中,GC Roots包括:

  1. 虚拟机栈中引用的对象。
  2. 方法区中类静态属性实体引用的对象。
  3. 方法区中常量引用的对象。
  4. 本地方法栈中JNI引用的对象。
  • GC的时机是什么?
    (1)程序调用System.gc时可以触发。
    (2)系统自身来决定GC触发的时机(根据Eden区和From Space区的内存大小来决定。当内存大小不足时,则会启动GC线程并停止应用线程)。
  • GC做了哪些事?
    主要做了清理对象,整理内存的工作。
  • GC常用算法
    GC常用算法有:标记-清除算法,标记-压缩算法,复制算法,分代收集算法。目前主流的JVM(HotSpot)采用的是分代收集算法。
    标记-清除算法
    为每个对象存储一个标记位,记录对象的状态(活着或是死亡)。分为两个阶段,一个是标记阶段,这个阶段内,为每个对象更新标记位,检查对象是否死亡;第二个阶段是清除阶段,该阶段对死亡的对象进行清除,执行 GC 操作。
    标记-压缩算法(标记-整理)
    标记-压缩法是标记-清除法的一个改进版。同样,在标记阶段,该算法也将所有对象标记为存活和死亡两种状态;不同的是,在第二个阶段,该算法并没有直接对死亡的对象进行清理,而是将所有存活的对象整理一下,放到另一处空间,然后把剩下的所有对象全部清除。这样就达到了标记-整理的目的。
    复制算法
    该算法将内存平均分成两部分,然后每次只使用其中的一部分,当这部分内存满的时候,将内存中所有存活的对象复制到另一个内存中,然后将之前的内存清空,只使用这部分内存,循环下去。
    分代收集算法
    现在的虚拟机垃圾收集大多采用这种方式,它根据对象的生存周期,将堆分为新生代(Young)和老年代(Tenure)。在新生代中,由于对象生存期短,每次回收都会有大量对象死去,那么这时就采用复制算法。老年代里的对象存活率较高,没有额外的空间进行分配担保,所以可以使用标记-整理 或者 标记-清除。

4 JVM调优的工具有哪些?

JDK 自带了很多监控工具,都位于 JDK 的 bin 目录下,其中最常用的是 jconsole 和 jvisualvm 这两款视图监控工具。

  1. jconsole:用于对 JVM 中的内存、线程和类等进行监控;
  2. jvisualvm:JDK 自带的全能分析工具,可以分析:内存快照、线程快照、程序死锁、监控内存的变化、gc 变化等。

5.常用的 JVM 调优的参数都有哪些?

XX比X的稳定性更差,并且版本更新不会进行通知和说明。
-Xms:s为strating,表示堆内存起始大小。
-Xmx:x为max,表示最大的堆内存(一般来说-Xms-Xmx的设置为相同大小,因为当heap自动扩容时,会发生内存抖动,影响程序的稳定性)。
-Xmn:n为new,表示新生代大小(-Xss:规定了每个线程虚拟机栈(堆栈)的大小)。
-XX:SurvivorRator=8 表示堆内存中新生代、老年代和永久代的比为8:1:1-XX:PretenureSizeThreshold=3145728表示当创建(new)的对象大于3M的时候直接进入。
-XX:MaxTenuringThreshold=15表示当对象的存活的年龄(minor gc一次加1)大于多少时,进入老年代。
-XX:-DisableExplicirGC表示是否(+表示是,-表示否)打开GC日志。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大梦谁先觉i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值