什么是JVM?
JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设施的标准,它是一个虚构进去的计算机,是通过在理论的计算机上仿真模仿各种计算机性能来实现的。
Java语言的一个十分重要的特点就是与平台的无关性。而应用Java虚拟机是实现这一特点的要害。个别的高级语言如果要在不同的平台上运行,至多须要编译成不同的指标代码。而引入Java语言虚拟机后,Java语言在不同平台上运行时不须要从新编译。Java语言应用Java虚拟机屏蔽了与具体平台相干的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的指标代码(字节码),就能够在多种平台上不加批改地运行。Java虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行。这就是Java的可能“一次编译,到处运行”的起因。
Java类加载过程
java类加载须要经验一下7个过程:
1.加载
加载是类加载的第一个过程,在这个阶段,将实现一下三件事件:
- 通过一个类的全限定名获取该类的二进制流。
- 将该二进制流中的动态存储构造转化为办法去运行时数据结构。
- 在内存中生成该类的 class对象,作为该类的数据拜访入口。
2.验证
验证的目标是为了确保 Class文件的字节流中的信息不可危害到虚拟机。
在该阶段次要实现以下四种验证:
文件格式验证
:验证字节流是否合乎Clas文件的标准,如主次版本号是否在以后虚拟机范畴内,常量池中的常量是否有不被反对的类型元数据验证
:对字节码形容的信息进行语义剖析,如这个类是否有父类,是否集成了不被继承的类等。字节码验证
:是整个验证过程中最简单的一个阶段,通过验证数据流和控制流的剖析,确定程序语义是否正确,次要针对办法体的验证。如:办法中的类型转换是否正确,跳转指令是否正确等·符号援用验证:这个动作在前面的解析过程中产生,次要是为了确保解析动作能正确执行。
3.筹备
筹备阶段是为类的动态变量分配内存并将其初始化为默认值,这些内存都将在办法区中进行调配。筹备阶段不调配类中的实例变量的内存,实例变量将会在对象实例化时随着对象一起调配在Java堆中。
//在筹备阶段vlue初始值为0,在初始化阶段才会变为123。public static int value=123;
4.解析
该阶段次要实现符号援用到间接援用的转换动作。解析动作并不一定在初始化动作实现之前,也有可能在初始化之后。
5.初始化
初始化时类加载的最初一步,后面的类加载过程,除了在加载阶段用户应用程序能够通过自定义类加载器参加之外,其余动作齐全由虚拟机主导和管制。到了初始化阶段,才真正开始执行类中的定义的java程序代码。
6.应用
7.卸载
深拷贝和浅拷贝
- 浅拷贝(shallowCopy):减少了一个指针指向已存在的内存地址。
- 深拷贝(deepCopy):减少了一个指针并且申请了一个新的内存,使这个减少的指针指向这个新的内存。
- 浅复制:指向被复制的内存地址,如果原地址产生扭转,那么浅复制进去的对象也会相应的扭转。
- 深复制:在计算机中开拓一块新的内存地址用于寄存复制的对象。
应用深拷贝的状况下,开释内存的时候不会因为呈现浅拷贝时开释同一个内存的谬误。
常量池是什么
能够了解为class文件之中的资源仓库,它是class文件构造中与其余我的项目关联最多的数据类型,也是占用class文件空间最大的数据我的项目之一,同时它还是class文件中第一个呈现表类型的数据我的项目.
因为常量池的数量是不固定的,所以在常量池入口须要搁置一项u2(即2个字节)类型的数据,代表常量池容量计数值(constant-pool-count)(从1开始,将0示意不援用任何常量).
常量池中次要寄存两大类常量:
- 字面量(Literal):比拟靠近于Java语言层面的常量概念,如文本字符串,申明为final的常量值.
- 符号援用(Synbolic Reference):包含如下三类常量:
①类和接口的全限定名(Fully Qualified Name)
②字段的名称和描述符(Descriptor)
③办法的名称和描述符
常量池在class文件的什么地位?
System.gc()和Runtime.gc()会做什么事件?
用来提醒JVM要进行垃圾回收。然而,立刻开始还是提早进行垃圾回收取决于JVM。
Java内存调配是怎么的?
- 寄存器:咱们无法控制。
- 动态域: static定义的动态成员。
- 常量池:编译时被确定并保留在.class文件中的(final)常量值和和一些文本润饰的符号援用(类和接口的全限定名,字段的名称和描述符,办法和名称和描述符)。
- 非RAM存储:硬盘等永恒存储空间。
- 堆内存:new创立的对象和数组,由Java虚拟机主动垃圾回收器治理,存取速度慢。
- 栈内存:根本类型的变量和对象的援用变量(堆内存空间的拜访地址),速度快,能够共享,然而大小与生存期必须确定,不足灵活性。
新生代垃圾回收器和老年代垃圾回收器都有哪些?有什么区别?
新生代回收器:Serial
、ParNew
、Parallel Scavenge
老年代回收器:Serial Old
、Parallel Old
、CMS
整堆回收器:G1
新生代垃圾回收器个别采纳的是复制算法,复制算法的长处是效率高,毛病是内存利用率低;老年代回收器个别采纳的是标记-整顿的算法进行垃圾回收。
简述分代垃圾回收器是怎么工作的?
分代回收器有两个分区:老生代和新生代,新生代默认的空间占比总空间的 1/3,老生代的默认占比是 2/3。
新生代应用的是复制算法,新生代里有 3 个分区:Eden
、To Survivor
、From Survivor
,它们的默认占比是 8:1:1,它的执行流程如下:
- 把
Eden + From Survivor
存活的对象放入To Survivor
区; - 清空
Eden
和From Survivor
分区; From Survivor
和To Survivor
分区替换,From Survivor
变To Survivor
,To Survivor
变From Survivor
。
每次在 From Survivor 到 To Survivor 挪动时都存活的对象,年龄就 +1,当年龄达到 15(默认配置是 15)时,降级为老生代。大对象也会间接进入老生代。
老生代当空间占用达到某个值之后就会触发全局垃圾发出,个别应用标记整顿的执行算法。以上这些周而复始就形成了整个分代垃圾回收的整体执行流程。
说一下 JVM 调优的工具?
JDK 自带了很多监控工具,都位于 JDK 的 bin 目录下,其中最罕用的是 jconsole
和 jvisualvm
这两款视图监控工具。
- jconsole:用于对 JVM 中的内存、线程和类等进行监控;
- jvisualvm:JDK 自带的全能剖析工具,能够剖析:内存快照、线程快照、程序死锁、监控内存的变动、gc 变动等。
Java堆的构造是什么样子的?什么是堆中的永恒代(Perm Gen space)?
JVM的堆是运行时数据区,所有类的实例和数组都是在堆上分配内存。它在JVM启动的时候被创立。对象所占的堆内存是由主动内存管理系统也就是垃圾收集器回收。
堆内存是由存活和死亡的对象组成的。存活的对象是利用能够拜访的,不会被垃圾回收。死亡的对象是利用不可拜访尚且还没有被垃圾收集器回收掉的对象。始终到垃圾收集器把这些对象回收掉之前,他们会始终占据堆内存空间。
finalize()办法什么时候被调用?析构函数finalization)目标是什么?
垃圾回收器(garbage collector)决定回收某对象时,就会运行该对象的 finalize办法,然而在Java中很可怜,如果内存总是短缺的,那么垃圾回收可能永远不会进行,也就是说 finalize可能永远不被执行,显然指望它做收尾工作是靠不住的。它最次要的用处是回收非凡渠道申请的内存。Java程序有垃圾回收器,所以个别状况下内存问题不必程序员操心。但有一种 JNI(Java Native Interface)调用non-java程序(C或C++), finalize()的工作就是回收这部分的内存。
什么是分布式垃圾回收(DGC)?它是如何工作的?
DGC叫做分布式垃圾回收。RMI应用DGC来做主动垃圾回收。因为RMI蕴含了跨虚拟机的近程对象的援用,垃圾回收是很艰难的。DGC应用援用计数算法来给近程对象提供主动内存治理。