面试突击JVM篇

JVM的组成

JVM 是 Java 虚拟机 Java Virtual Machine 的缩写,JVM 是一种用于计算设备的规范。引入 Java 语言虚拟机后,Java 语言在不同平台上运行时不需要重新编译。Java 语言使用 Java 虚拟机屏蔽了与具体平台相关的信息,使得 Java 语言编译程序只需生成在 Java 虚拟机上运行的目标代码(字节码),就可以在不同机器上进行运行。

1 类加载器

1、JVM三种预定义类型类加载器

当JVM启动的时候,Java开始使用如下三种类型的类加载器:

启动(Bootstrap)类加载器:启动类加载器是用本地代码实现的类加载器,它负责将JAVA_HOME/lib下面的核心类库或-Xbootclasspath选项指定的jar包等虚拟机识别的类库加载到内存中。由于启动类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用。具体可由启动类加载器加载到的路径可通过System.getProperty(“sun.boot.class.path”)查看。

扩展(Extension)类加载器:扩展类加载器是由Sun的ExtClassLoader(sun.misc.Launcher$ExtClassLoader)实现的,它负责将JAVA_HOME /lib/ext或者由系统变量-Djava.ext.dir指定位置中的类库加载到内存中。开发者可以直接使用标准扩展类加载器,具体可由扩展类加载器加载到的路径可通过System.getProperty(“java.ext.dirs”)查看。

系统(System)类加载器:系统类加载器是由 Sun 的 AppClassLoader(sun.misc.Launcher$AppClassLoader)实现的,它负责将用户类路径(java -classpath或-Djava.class.path变量所指的目录,即当前类所在路径及其引用的第三方类库的路径,如第四节中的问题6所述)下的类库加载到内存中。开发者可以直接使用系统类加载器,具体可由系统类加载器加载到的路径可通过System.getProperty(“java.class.path”)查看。

2 运行时数据区

2.1方法区(元数据区)

方法区保存在着被加载过的每一个类的信息;这些信息由类加载器在加载类的时候,从类的源文件中抽取出来;static变量信息也保存在方法区中;可以看做是将类(Class)的元数据,保存在方法区里;方法区是线程共享的;方法区的大小不必是固定的,jvm可以根据应用的需要动态调整。jvm也可以允许用户和程序指定方法区的初始大小,最小和最大限制;方法区同样存在垃圾收集,因为通过用户定义的类加载器可以动态扩展Java程序,这样可能会导致一些类,不再被使用,变为垃圾。这时候需要进行垃圾清理。

2.2 堆

堆区 Heap 是 JVM 中最大的一块内存区域,基本上所有的对象实例都是在堆上分配空间。堆区细分为年轻代和老年代,其中年轻代又分为 Eden、S0、S1 三个部分,他们默认的比例是 8:1:1 的大小。对象一般是在新生代创建,经过引用计数法和可达性分析算法进行垃圾的标记回收,最终存活的对象在老年代中被调用,当然有些比较大的对象会直接在老年代中被创建。

2.3 虚拟机栈

2.3.1概念
由于跨平台性的设计, Java的指令都是根据栈来设计的。不同平台CPU架构不同,所以不能设计为基于寄存器的。优点是跨平台,指令集小,编译器容易实现,缺点是性能下降,实现同样的功能需要更多的指令。
栈是运行时的单位,而堆是存储的单位。即: 栈解决程序的运行问题,即程序如何执行,或者说如何处理数据。堆解决的是数据存储的问题,即数据怎么放、放在哪儿。

2.3.2Java虚拟机栈是什么?
Java虚拟机栈(Java virtual Machine stack) ,早期也叫Java栈。每个线程在创建时都会创建一个虚拟机栈,其内部保存一个个的栈帧(stack Frame) ,对应着一次次的Java方法调用。

线程私有
生命周期生命周期和线程一致
主管Java程序的运行,它保存方法的局部变量(8种基本数据类型、对象的引用地址)、部分结果,并参与方法的调用和返回

栈的特点:
栈是一种快速有效的分配存储方式,访问速度仪次于程序计数器
JVM直接对Java栈的操作只有两个:每个方法执行伴随着进栈(入栈、压栈) 和 执行结束后的出栈工作
对于栈来说不存在垃圾回收问题GC,但存在内存移出问题OOM

2.4程序计数器

概念
程序计数器(Program Counter Register)是一块较小的内存空间,它可以看做是当前线程所执行的字节码的行号指示器。在虚拟机的概念模型里(仅是概念模型,各种虚拟机可能会通过一些更高效的方式去实现),字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。

程序计数器的特点
1.线程隔离性,每个线程工作时都有属于自己的独立计数器。
2.执行java方法时,程序计数器是有值的,且记录的是正在执行的字节码指令的地址(参考上一小节的描述)。
3.执行native本地方法时,程序计数器的值为空(Undefined)。因为native方法是java通过JNI直接调用本地C/C++库,可以近似的认为native方法相当于C/C++暴露给java的一个接口,java通过调用这个接口从而调用到C/C++方法。由于该方法是通过C/C++而不是java进行实现。那么自然无法产生相应的字节码,并且C/C++执行时的内存分配是由自己语言决定的,而不是由JVM决定的。
4.程序计数器占用内存很小,在进行JVM内存计算时,可以忽略不计。
5.程序计数器,是唯一一个在java虚拟机规范中没有规定任何OutOfMemoryError的区域。
在这里插入图片描述

2.5本地方法栈

特点
本地方法栈(Native Method Stacks)与 Java 虚拟机栈所发挥的作用是非常相似的,其区别不过是虚拟机栈为虚拟机执行 Java 方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的 Native 方法服务。虚拟机规范中对本地方法栈中的方法使用的语言、使用方式与数据结构并没有强制规定,因此具体的虚拟机可以自由实现它。
在这里插入图片描述

3 执行引擎

概念
执行引擎是Java虚拟机核心的组成部分,它是用于负责装载字节码到其内部,但是字节码并不能直接在操作系统上运行,那么执行引擎就是将字节码指令解释/编译为对应平台上的本地机器指令。简单来说,JVM执行引擎充当了将高级语言翻译为机器语言的翻译者。

执行引擎的工作过程
1、执行引擎在执行的过程中究竟需要执行什么样的字节码指令安全依赖于PC寄存器。
2、每当执行完一项指令操作后,PC寄存器就会更新下一条需要被执行的指令地址。
3、当然方法在执行的过程中,执行引擎有可能通过存储在局部变量表中的对象引用准确定位到存储在Java堆区中的对象实例信息,以及通过对象头中的元数据指针定位到目标对象的类型信息。
在这里插入图片描述

建议阅读本文档的方式 本文档提供详细的目录,建议大家使用电脑阅读。如果大家用手机阅读的话,可以下载一个不错的PDF阅读器,比如 很多人常用的福昕PDF阅读器。 本文档提供详细的目录,大家可以根据自己的实际需要选择自己薄弱的知识章节阅读。 前言 不论是校招还是社招都避免不了各种面试、笔试,如何去准备这些东西就显得格外重要。不论是笔试还是面试都是有 章可循的,我这个“有章可循”说的意思只是说应对技术面试是可以提前准备。 运筹帷幄之后,决胜千里之外!不打毫无准备的仗,我觉得大家可以先从下面几个方面来准备面试: 1. 自我介绍。(你可千万这样介绍:“我叫某某,性别,来自哪里,学校是那个,自己爱干什么”,记住:多说点简 历上没有的,多说点自己哪里比别人强!) 2. 自己面试中可能涉及哪些知识点、那些知识点是重点。 3. 面试中哪些问题会被经常问到、面试中自己改如何回答。(强烈不推荐背题,第一:通过背这种方式你能记住多 少?能记住多久?第二:背题的方式的学习很难坚持下去!) 4. 自己的简历该如何写。 “80%的offer掌握在20%的人手中” 这句话也不是不无道理的。决定你面试能否成功的因素中实力固然占有很大一部 分比例,但是如果你的心态或者说运气不好的话,依然无法拿到满意的 offer。运气暂且不谈,就拿心态来说,千万 不要因为面试失败而气馁或者说怀疑自己的能力,面试失败之后多总结一下失败的原因,后面你就会发现自己会越来 越强大。 另外,大家要明确的很重要的几点是: 1. 写在简历上的东西一定要慎重,这可能是面试官大量提问的地方; 2. 大部分应届生找工作的硬伤是没有工作经验或实习经历; 3. 将自己的项目经历完美的展示出来非常重要。 笔主能力有限,如果有不对的地方或者和你想法不同的地方,敬请雅正、不舍赐教。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值