长春建设股份有限公司,平阳网站优化,云服务器建设网站教程,免费网站导航建设1、JVM的主要组成部分有哪些 JVM主要分为下面几部分 类加载器#xff1a;负责将字节码文件加载到内存中 运行时数据区#xff1a;用于保存java程序运行过程中需要用到的数据和相关信息 执行引擎#xff1a;字节码文件并不能直接交给底层操作系统去执行#xff0c;因此需要…1、JVM的主要组成部分有哪些 JVM主要分为下面几部分 类加载器负责将字节码文件加载到内存中 运行时数据区用于保存java程序运行过程中需要用到的数据和相关信息 执行引擎字节码文件并不能直接交给底层操作系统去执行因此需要特定的命令解析器执行引擎将字节码翻译成底层系统指令 本地库接口会被执行引擎调用参与字节码的翻译
在这里面最主要的部分是运行时数据区它又由五部分构成分别是堆、方法区、栈、本地方法栈、程序计数器
堆是对象实例存储的主要区域方法区可以认为是堆的一部分用于存储已被虚拟机加载的信息比如常量、静态变量等等栈是程序方法运行的主要区域栈里面存的是栈帧栈帧里面存的是局部变量表、操作数栈、动态链接、方法出口等信息本地方法栈与栈功能相同区别在于本地方法栈执行的是本地方法即一个Java调用非Java代码的接口程序计数器主要存放的是当前线程所执行的字节码的行号用于记录正在执行的字节码指令的地址
2、堆栈的区别是什么
堆和栈都是JVM的主要组成部分不同点在于
栈内存一般会用来存储局部变量和方法调用但堆内存是用来存储Java对象和数组的堆会GC垃圾回收而栈不会栈内存是线程私有的而堆内存是线程共有的两者异常错误不同栈空间不足java.lang.StackOverFlowError堆空间不足java.lang.OutOfMemoryError
3、JVM的类加载器有哪些
类加载器的主要作用就是将字节码文件加载到JVM中从而让Java程序能够启动起来。根据各自加载范围的不同主要划分为四种类加载器 启动类加载器(BootStrap ClassLoader)用于加载JAVA_HOME/jre/lib目录下的类库 扩展类加载器(ExtClassLoader)用于加载JAVA_HOME/jre/lib/ext目录中的类库 应用类加载器(AppClassLoader)用于加载classPath下的类也就是加载开发者自己编写的Java类 自定义类加载器开发者自定义类继承ClassLoader实现自定义类加载规则
4、什么是双亲委派模型
双亲委派模型是Java中的一种类加载机制。
在双亲委派模型中类加载器之间形成了一种层次继承关系从顶端开始依次是启动类加载器-扩展类加载器-应用类加载器-自定义类加载器
当一个类加载器需要加载某个类时它首先会委派给其上层类加载器去尝试加载该类。如果父类加载器无法加载该类子类加载器才会尝试加载。
这种层次关系形成了一个从上到下的委派链。
双亲委派模型的主要目的是保证Java类的安全性和避免类的重复加载。当一个类加载器收到加载请求时它会首先检查自己是否已经加载了该类。
如果已经加载则直接返回该类的Class对象如果未加载则将加载请求委派给父类加载器。
父类加载器也会按照同样的方式进行检查直到顶层的启动类加载器。如果顶层的启动类加载器无法加载该类那么子类加载器会尝试自己加载。
这样可以避免同一个类被不同的类加载器加载多次确保类的唯一性。
双亲委派模型的优势在于能够保证类的一致性和安全性。
通过委派链的机制可以避免恶意代码通过自定义的类加载器加载替换系统核心类从而提高了Java程序的安全性。
此外通过双亲委派模型可以实现类的共享和重用减少内存占用和加载时间提高了系统的性能。
5、说一下类加载器的执行过程
类从被加载到虚拟机内存中开始直到卸载出内存为止整个生命周期包括了7个阶段加载、验证、准备、解析、初始化、使用、卸载
加载: 这个阶段会在内存中生成一个代表这个类的java.lang.Class对象验证: 这个阶段的主要目的是为了确保Class文件包含的信息符合当前虚拟机的要求并且不会危害虚拟机自身的安全准备: 这个阶段正式为类变量分配内存并设置类变量的初始值注意这里的初始值指的是默认值而不是代码后的实际值解析: 这个阶段将符号引用替换为直接引用比如方法中调用了其他方法方法名可以理解为符号引用而直接引用就是使用指针直接引用方法初始化: 这个阶段是执行类构造器方法的过程是类加载的最后一步到了这一步Java虚拟机才开始真正执行类中定义的Java程序代码(字节码)使用: 这个节点程序在运行卸载: 这个阶段类Class对象被GC 6、怎么判断对象是否可以被回收
在堆中存放着几乎所有的对象实例垃圾收集器在对堆进行回收前第一件事就是要确定哪些对象是要回收的
JVM认为不被引用的对象就是可以被回收的对象而它确认对象是否还在被引用的算法主要有两种引用计数法和可达性分析算法 引用计数法 在对象头处维护一个counter每增加一次对该对象的引用计数器自加如果对该对象的引用失联则计数器自减 当counter为0时表明该对象已经被废弃不处于存活状态, 但是此方法存在问题假设两个对象相互引用始终无法释放counter则永远不能GC 可达性分析算法 通过一系列为GC Roots的对象作为起始点从这些节点开始向下搜索搜索所走过的路径称为引用链 当一个对象到GC Roots没有任何引用链相连时则证明该对象是不可用的 可以作为GC Roots的对象一般有栈中引用的对象 、方法区中类静态属性引用的对象以及
7、JVM的垃圾回收算法有哪些
目前JVM中的垃圾回收算法主要有四个分别是标记清除算法、标记-整理算法、复制算法和分代收集算法 标记清除算法是将垃圾回收分为2个阶段分别是标记和清除 它会先使用根据可达性分析算法找到垃圾资源进行标记然后对这些标记为可回收的内容进行垃圾回收 这种算法的主要不足有两个 效率问题标记和清除阶段都要遍历多有对象并且在GC时需要停止应用程序对于交互性要求比较高的应用而言这个体验是非常差的 空间问题对象被回收之后会产生大量不连续的内存碎片当需要分配较大对象时由于找不到合适的空闲内存而不得不再次触发垃圾回收动作 标记整理算法也是将垃圾回收分为2个阶段分别是标记和整理清除 它的第一阶段也是会先将存活的对象先标记出来 不一样的地方在于第二阶段它会将所有存活的对象向前移动放在一起然后将无用空间回收这样就会出现连续的可用空间了 所以它解决了空间碎片问题但是效率低的问题依旧存在 复制算法将原有的内存空间一分为二每次只用其中的一半 在垃圾回收时将正在使用的对象复制到另一个内存空间中然后将当前内存空间清空交换两个内存的角色完成垃圾的回收。 这种算法的缺点在于分配2块内存空间在同一个时刻只能使用一半内存使用率较低 分代收集算法它会将整个堆内存分成几部分空间每个空间中放入不同类型的对象然后各自适合的算法回收 在JDK8时堆被分为了两份新生代和老年代默认空间比例为1:2 对于新生代内部又被分为了三个区域Eden区S0区S1区默认空间比例为811 它的基本工作机制是
当创建一个对象的时候这个对象会被分配在新生代的Eden区当Eden区要满了时候触发MinorGC
当进行MinorGC后此时在Eden区存活的对象被移动到S0区并且当前对象的年龄会加1清空Eden区
当再一次触发MinorGC的时候会把Eden区中存活下来的对象和S0中的对象移动到S1区中这些对象的年龄会加1清空Eden区和S0区
当再一次触发YoungGC的时候会把Eden区中存活下来的对象和S1中的对象移动到S0区中这些对象的年龄会加1清空Eden区和S1区
对象的年龄达到了某一个限定的值默认15岁那么这个对象就会进入到老年代中除此之外大对象也会直接放入老年代空间
当老年代满了之后触发FullGC**。**FullGC同时回收新生代和老年代
在上述过程中新生代中的对象存活率比较低所以选用复制算法老年代中对象存活率高所以使用标记-整理算法
小细节 当对新生代产生GCMinorGC老年代代产生GCMajor GC 新生代和老年代产生FullGC Minor GC非常频繁一般回收速度也很快Major GC一般会伴随一次Minor GCMajor GC的速度要慢很多一般要比Minor GC慢10倍 占用内存较大的对象对于虚拟机内存分配是一个坏消息虚拟机提供了一个-XX:PretenureSizeThreshold让大于这个设置的对象直接存入老年代 虚拟机给每个对象定义了一个Age年龄计数器对象在Eden中出生并经过第一次Minor GC后仍然存活年龄1此后每熬过一次Minor GC则年龄1
当年龄增加到一定程度(默认15岁)就会晋升到老年代。可通过参数设置晋升年龄 -XX:MaxTenuringThreshold
8、JVM的垃圾回收器都有哪些
JVM中常见的一些垃圾回收器有 新生代回收器Serial、ParNew、Parallel Scavenge 老年代回收器Serial Old、Parallel Old、CMS 整堆回收器G1
新生代垃圾回收器一般采用的是复制算法复制算法的优点是效率高缺点是内存利用率低
老年代回收器一般采用的是标记-整理的算法进行垃圾回收