文本已收录至个人GitHub仓库,欢迎Star:github.com/bin39232820…
种一棵树最好的时间是十年前,其次是如今
我知道不少人不玩qq了,可是怀旧一下,欢迎加入六脉神剑Java菜鸟学习群,群聊号码:549684836 鼓励你们在技术的路上写博客java
絮叨
前面的章节git
今天呢,给你们讲关于JVM的面试题,可是太多了,我也挑不全,讲讲比较典型的,可是全部题目的答案仍是前面四个章节的基础,我以为最难的是类文件结构,这个真的搞死人。哈哈,废话很少说咱们来看题程序员
JVM内存分哪几个区,每一个区的做用是什么?
Java虚拟机主要分为如下一个区: github
- 方法区:
- 有时候也成为永久代,在该区内不多发生垃圾回收,可是并不表明不发生GC,在这里进行的GC主要是对方法区里的常量池和对类 型的卸载
- 方法区主要用来存储已被虚拟机加载的类的信息、常量、静态变量和即时编译器编译后的代码等数据。
- 该区域是被线程共享的。
- 方法区里有一个运行时常量池,用于存放静态编译产生的字面量和符号引用。该常量池具备动态性,也就是说常量并不必定是编 译时肯定,运行时生成的常量也会存在这个常量池中。
- 虚拟机栈:
- 虚拟机栈也就是咱们日常所称的栈内存,它为java方法服务,每一个方法在执行的时候都会建立一个栈帧,用于存储局部变量表、操 做数栈、动态连接和方法出口等信息。
- 虚拟机栈是线程私有的,它的生命周期与线程相同。
- 局部变量表里存储的是基本数据类型、returnAddress类型(指向一条字节码指令的地址)和对象引用,这个对象引用有多是指 向对象起始地址的一个指针,也有多是表明对象的句柄或者与对象相关联的位置。局部变量所需的内存空间在编译器间肯定
- 操做数栈的做用主要用来存储运算结果以及运算的操做数,它不一样于局部变量表经过索引来访问,而是压栈和出栈的方式
- 每一个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程当中的动态链接.动态连接就是将常量池中的符号引用在运行期转化为直接引用。
- 本地方法栈
- 本地方法栈和虚拟机栈相似,只不过本地方法栈为Native方法服务。
- 堆
- Java堆是全部线程所共享的一块内存,在虚拟机启动时建立,几乎全部的对象实例都在这里建立,所以该区域常常发生垃圾回收操做 。
- 程序计数器
- 内存空间小,字节码解释器工做时经过改变这个计数值能够选取下一条须要执行的字节码指令,分支、循环、跳转、异常处理和线程恢复等功能都须要依赖这个计数器完成。该内存区域是惟一一个java虚拟机规范没有规定任何OOM状况的区域。
如和判断一个对象是否存活?(或者GC对象的断定方法)
答案再前面的章节web
简述Java垃圾回收机制?
在Java中,程序员是不须要显示的去释放一个对象的内存的,而是由虚拟机自行执行。在JVM中,有一个垃圾回收线程,它是低优先级的,在正常状况下是不会执行的,只有在虚拟机空闲或者当前堆内存不足时,才会触发执行,扫面那些没有被任何引用的对象,并将它们添加到要回收的集合中,进行回收。面试
Java中垃圾收集的方法有哪些?
问的3种回收算法 在前面的章节算法
java类加载过程?
问的是类加载的7个过程 加载 验证 准备 解析 初始化 运行 死亡 这7个过程,每一个过程作了什么 ,也是再我前面的章节数据库
类加载器双亲委派模型机制?
简单来讲就是8个字,向上检查,向下加载。具体能够看我前面的章节安全
什么是类加载器,类加载器有哪些?
实现经过类的权限定名获取该类的二进制字节流的代码块叫作类加载器。服务器
主要有一下四种类加载器:
- 启动类加载器(Bootstrap ClassLoader)用来加载java核心类库,没法被java程序直接引用。
- 扩展类加载器(extensions class loader):它用来加载 Java 的扩展库。Java 虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载 Java 类。
- 系统类加载器(system class loader):它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。通常来讲,Java 应用的类都是由它来完成加载的。能够经过 ClassLoader.getSystemClassLoader()来获取它。
- 用户自定义类加载器,经过继承 java.lang.ClassLoader类的方式实现。
Tomcat 的类加载模型
想一想 Tomcat 为啥要打破双亲委派模型
首先,咱们来问个问题:
Tomcat 若是使用默认的类加载机制行不行?
咱们思考一下:Tomcat是个web容器, 那么它要解决什么问题:
- 一个web容器可能须要部署两个应用程序,不一样的应用程序可能会依赖同一个第三方类库的不一样版本,不能要求同一个类库在同一个服务器只有一份,所以要保证每一个应用程序的类库都是独立的,保证相互隔离。
- 部署在同一个web容器中相同的类库相同的版本能够共享。不然,若是服务器有10个应用程序,那么要有10份相同的类库加载进虚拟机,这是扯淡的。
- web容器也有本身依赖的类库,不能于应用程序的类库混淆。基于安全考虑,应该让容器的类库和程序的类库隔离开来。
- web容器要支持jsp的修改,咱们知道,jsp 文件最终也是要编译成class文件才能在虚拟机中运行,但程序运行后修改jsp已是司空见惯的事情,不然要你何用? 因此,web容器须要支持 jsp 修改后不用重启。
再看看咱们的问题:Tomcat 若是使用默认的类加载机制行不行?
答案是不行的。为何?咱们看,第一个问题,若是使用默认的类加载器机制,那么是没法加载两个相同类库的不一样版本的,默认的累加器是无论你是什么版本的,只在意你的全限定类名,而且只有一份。第二个问题,默认的类加载器是可以实现的,由于他的职责就是保证惟一性。第三个问题和第一个问题同样。咱们再看第四个问题,咱们想咱们要怎么实现jsp文件的热修改(楼主起的名字),jsp 文件其实也就是class文件,那么若是修改了,但类名仍是同样,类加载器会直接取方法区中已经存在的,修改后的jsp是不会从新加载的。那么怎么办呢?咱们能够直接卸载掉这jsp文件的类加载器,因此你应该想到了,每一个jsp文件对应一个惟一的类加载器,当一个jsp文件修改了,就直接卸载这个jsp类加载器。从新建立类加载器,从新加载jsp文件。
你有没有遇到过OutOfMemory问题?你是怎么来处理这个问题的?处理 过程当中有哪些收获?
常见的缘由
- 内存加载的数据量太大:一次性从数据库取太多数据;
- 集合类中有对对象的引用,使用后未清空,GC不能进行回收;
- 代码中存在循环产生过多的重复对象;
- 启动参数堆内存值小。
JDK 1.8以后Perm Space有哪些变更? MetaSpace⼤⼩默认是⽆限的么? 仍是大家会经过什么⽅式来指定⼤⼩?
JDK 1.8后用元空间替代了 Perm Space;字符串常量存放到堆内存中。
MetaSpace大小默认没有限制,通常根据系统内存的大小。JVM会动态改变此值。
-XX:MetaspaceSize:分配给类元数据空间(以字节计)的初始大小(Oracle逻辑存储上的初始高水位,the initial high-water-mark)。此值为估计值,MetaspaceSize的值设置的过大会延长垃圾回收时间。垃圾回收事后,引发下一次垃圾回收的类元数据空间的大小可能会变大。
-XX:MaxMetaspaceSize:分配给类元数据空间的最大值,超过此值就会触发Full GC,此值默认没有限制,但应取决于系统内存的大小。JVM会动态地改变此值。
jstack 是⼲什么的? jstat 呢?若是线上程序周期性地出现卡顿,你怀疑可 能是 GC 致使的,你会怎么来排查这个问题?线程⽇志⼀般你会看其中的什么 部分?
jstack 用来查询 Java 进程的堆栈信息。
jvisualvm 监控内存泄露,跟踪垃圾回收、执行时内存、cpu分析、线程分析。
StackOverflow异常有没有遇到过?⼀般你猜想会在什么状况下被触发?如何指定⼀个线程的堆栈⼤⼩?⼀般大家写多少?
栈内存溢出,通常由栈内存的局部变量过爆了,致使内存溢出。出如今递归方法,参数个数过多,递归过深,递归没有出口
跟JVM内存相关的几个核心参数图解
如何启动系统的时候设置JVM的启动参数
结尾
这篇到时候看到好的就补充进去,先说这么多,而后是实战才是最重要的,你要有实际JVM调优经验,面试才是加分项,至于理论也仅仅是次要的。
平常求赞
好了各位,以上就是这篇文章的所有内容了,能看到这里的人呀,都是真粉。
创做不易,各位的支持和承认,就是我创做的最大动力,咱们下篇文章见
六脉神剑 | 文 【原创】若是本篇博客有任何错误,请批评指教,不胜感激 !