《二十不惑》,多看看JVM面试全解

最近要准备秋招了,会更新一些面试相关的知识

JRE和JDK的区别

JRE是Java Runtime Environment的缩写,顾名思义是java运行时环境,包含了java虚拟机,java基础类库。是使用java语言编写的程序运行所需要的软件环境,是提供给想运行java程序的用户使用的,还有所有的Java类库的class文件,都在lib目录下,并且都打包成了jar。

Jdk是Java Development Kit的缩写,顾名思义是java开发工具包,是程序员使用java语言编写java程序所需的开发工具包,是提供给程序员使用的。JDK包含了JRE,同时还包含了编译java源码的编译器javac,还包含了很多java程序调试和分析的工具:jconsole,jvisualvm等工具软件,还包含了java程序编写所需的文档和demo例子程序。

如果你需要运行java程序,只需安装JRE就可以了。如果你需要编写java程序,需要安装JDK。

引言

我们知道java能够实现跨平台运行,可以同一份代码在Windows和Linux平台下运行,而且知道实现跨平台是因为java有JVM.

那么为什么有了JVM就能实现java的跨平台运行呢?

JVM实现java跨平台运行原理
image-20200809094714383

Java虚拟机从软件侧面屏蔽了底层硬件指令层面的细节,也就是说,我们在操作系统的底层需要的是机器码,而java程序编译后生成的同一份字节码通过JVM虚拟机(当然需要不同的虚拟机),达到了将字节码解析为不同环境所需的机器码,从而实现了在编写程序时,我们不需要考虑在不同环境(Windows和Linux)下能用到的不同的类库,在java中,只需要编写程序,底层又JVM做底层的硬件指令的细节.


JVM

1.JVM是什么?

JVM它是Java Virtual Machine 的缩写,主要是通过在实际计算机模仿各种计算机功能来实现的,组成部分包括堆、方法区、栈、本地方法栈、程序计算器等部分组成的,其中方法回收堆和方法区是共享区,也就是谁都可以使用,而栈和程序计算器、本地方法栈区是归JVM的。Java能够被称为“一次编译,到处运行”的原因就是Java屏蔽了很多的操作系统平台相关信息,使得Java只需要生成在JVM虚拟机运行的目标代码也就是所说的字节码,就可以在多种平台运行。

image-20200809111434086

2.JVM的实现原理

  • 类装载器(ClassLoader)主要负责加载class文件,是否能执行主要取决于execution engine它是负责执行被加载类中包含的指令。有两种类加载器分别为启动类加载器和用户自定义类加载器,然而启动类加载器是JVM实现的一部分,用户自定义类加载器是Java程序一部分。
  • 本地方法栈(native method stack)主要作用是登记native方法,然后在execution engine执行的时候加载本地方法库。
  • 程序计数器,是指方法区中的方法字节码由引擎读取下一条指令,它是一个非常小的内存空间。为什么有这种东西呢,大家都知道每个线程都是有一个程序计数器的,是线程私有的,相当一个指针。
  • 方法区它是指线程共享的,谁都可以共享使用,我们通常用来保存装载类的元结构信息。
  • (heap)它是Java虚拟机用来存储对象实例的,比我们在开发过程使用的new对象,只要通过new创建的对象的内存的对象都在堆分配,注意一点的是堆中的对象内存需要等待垃圾器(GC)进行回收,也是Java虚拟机共享区。
  • 本地接口(native interface)作用是融合不同的编程语言为Java所用,注意底层是C、C++写的,学习JVM时了解C语言一些更好,最起码能看懂,这个方法的行为就是native method stack中登记native方法,然后在execution engine执行时加载native libraries的。

3.JVM调优

image-20200809111824693

我们的程序是基于JVM上面的,而多个程序组成的软件最终是运行在硬件上的(比如最终运行在我们的计算机电脑上),而计算机的内存是有限的,如果不断的运行程序,而不管产生的垃圾内存,这样JVM所占用的内存就会越来越大,从而导致最终占用很大的内存,导致计算机的其他功能无法正常运行,甚至项目崩溃.

这时,就需要定期的将程序运行所产生的垃圾内存进行回收

也就是给JVM设置一个占用最大内存的临界点:保证其他程序的正常运行,而且我们的程序也要能正常运行

Java 堆从 GC 的角度还可以细分为: 新生代(Eden 区From Survivor 区To Survivor 区)和老年

代。

image-20200809113818427

新生代

是用来存放新生的对象。一般占据堆的 1/3 空间。由于频繁创建对象,所以新生代会频繁触发

MinorGC 进行垃圾回收。新生代又分为 Eden 区、ServivorFrom、ServivorTo 三个区.

  • Eden区:Java 新对象的出生地(如果新创建的对象占用内存很大,则直接分配到老

    年代)。当 Eden 区内存不够的时候就会触发 MinorGC,对新生代区进行

    一次垃圾回收。

  • ServivorFrom:上一次GC的幸存者,作为这一次GC的被扫描的对象

  • ServivorTo:保留了一次 MinorGC 过程中的幸存者

MinorGC的过程

采用的是复制算法

1edenservicorFrom 复制到 ServicorTo,年龄+1

首先,把 Eden 和 ServivorFrom 区域中存活的对象复制到 ServicorTo 区域(如果有对象的年

龄以及达到了老年的标准,则赋值到老年代区),同时把这些对象的年龄+1(如果 ServicorTo 不

够位置了就放到老年区);

2:清空 edenservicorFrom

然后,清空 Eden 和 ServicorFrom 中的对象;

3ServicorTo ServicorFrom 互换

最后,ServicorTo 和 ServicorFrom 互换,原 ServicorTo 成为下一次 GC 时的 ServicorFrom

区。

老年代

主要存放应用程序中生命周期长的内存对象。

老年代的对象比较稳定,所以 MajorGC 不会频繁执行。在进行 MajorGC 前一般都先进行

了一次 MinorGC,使得有新生代的对象晋身入老年代,导致空间不够用时才触发。当无法找到足

够大的连续空间分配给新创建的较大对象时也会提前触发一次 MajorGC 进行垃圾回收腾出空间。

MajorGC 采用标记清除算法:首先扫描一次所有老年代,标记出存活的对象,然后回收没

有标记的对象。MajorGC 的耗时比较长,因为要扫描再回收。MajorGC 会产生内存碎片,为了减

少内存损耗,我们一般需要进行合并或者标记出来方便下次直接分配。当老年代也满了装不下的

时候,就会抛出 OOM(Out of Memory)异常。

总结:

1. 确认哪些内存需要回收?

GC能明确内存的占用,当内存不够时,GC就会启动并扫描哪些内存需要被回收

2. 什么时候回收?

JVM的垃圾回收算法,不是我们自主调用就立即执行的,而是等待程序认为合适的时间然后运行

3. 怎么回收?

GC采用垃圾回收算法:标记清除算法,复制算法,标记整理算法,分代收集

4. JVM怎么确认哪些对象是垃圾?(哪些对象已经"死亡"?)

引用计算法和根搜索算法

  • 引用计算法:在 Java 中,引用和对象是有关联的。如果要操作对象则必须用引用进行。因此,很显然一个简单的办法是通过引用计数来判断一个对象是否可以回收。简单说,即一个对象如果没有任何与之关联的引用,即他们的引用计数都不为 0,则说明对象不太可能再被用到,那么这个对象就是可回收对象。
  • 可达性分析(根搜索算法):为了解决引用计数法的循环引用问题,Java 使用了可达性分析的方法。通过一系列的“GC roots”对象作为起点搜索。如果在“GC roots”和一个对象之间没有可达路径,则称该对象是不可达的。要注意的是,不可达对象不等价于可回收对象,不可达对象变为可回收对象至少要经过两次标记过程。两次标记后仍然是可回收对象,则将面临回收。

5. 垃圾收集算法?

新生代采用的是复制算法,老生代采用的是Major GC

6. 为什么要将新生代和老生代,分代收集垃圾?

为了减少full GC的次数,因为在老生代进行full GC时,都会触发STW=stop the world不能提供任何服务,程序在此时不能进行任何的操作,相当于程序中断掉了,而这在我们程序中是不希望发生的,因此进行分代收集垃圾,新生代垃圾回收的次数多,老生代垃圾回收的次数少,从而减少了full GC,也就让STW触发的次数减少.

ull GC时,都会触发STW=stop the world不能提供任何服务,程序在此时不能进行任何的操作,相当于程序中断掉了,而这在我们程序中是不希望发生的,因此进行分代收集垃圾,新生代垃圾回收的次数多,老生代垃圾回收的次数少,从而减少了full GC,也就让STW触发的次数减少.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

炒冷饭

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

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

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

打赏作者

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

抵扣说明:

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

余额充值