网站404报错,成都创意网站设计,wordpress导购页面,龙岩做网站设计公司JVM面试题
1、JVM内存区域 Jvm包含两个子系统和两个组件。
1.1子系统
Class loader#xff08;类加载器#xff09;#xff1a;根据给定的全限定名类名#xff08;java.lang.object#xff09;来装载class文件到Runtime data area#xff08;运行时数据区#xff09;…JVM面试题
1、JVM内存区域 Jvm包含两个子系统和两个组件。
1.1子系统
Class loader类加载器根据给定的全限定名类名java.lang.object来装载class文件到Runtime data area运行时数据区的method方法区。
Execution engine执行引擎执行classes中的指令。
Native Interface本地接口与native libraries交互是其他编程语言交互的接口。
Runtime data area运行时数据区域JVM内存
作用
通过编译器将Java代码转换为字节码类加载器class loader再将字节码加载到内存中运行时数据区的方法区method字节码文件只是JVM的一套指令集规范不能直接交给底层操作系统执行需要特定的命令解析器执行引擎Execution engine将字节码翻译成底层系统指令再交给CPU执行过程中需要调用其他语言的本地库接口native interface实现整个程序的功能
类的加载将class文件中的二进制数据读入到内存中将其放在运行时数据区的方法区内然后在堆上创建一个java.lang.Class对象用来封装类在方法区内的数据结构。
1.2 运行时数据区 程序计数器当前线程所执行的字节码的行号指示器。通过改变这个计数器的值选取下一条需要执行的字节码指令。
Java虚拟机栈存储局部变量表、操作数栈、动态连接、方法出口等信息。服务JAVA方法
本地方法栈为虚拟机Native方法服务的这些方法底层是C语言编写直接与操作系统对接的方法。
堆内存中最大的一块被所有线程共享几乎所有对象实例都在这里分配内存。包括静态对象。
方法区存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据。
1.2.1 堆和栈的区别
物理地址
堆的物理地址分配对象是不连续的。性能较慢。在GC时考虑到不连续的分配因此有各种算法标记清除、复制、标记压缩、分代等
栈使用的是数据结构中的栈先进后出物理地址分配时连续的性能快。
内存分别
堆因为分配不是连续的分配的内存在运行期才确认大小不固定。
栈是连续的分配的内存大小在编译器就确认大小是固定的。
存放的内容
堆存放对象的实例和数组更关注数据的存储。
栈存放局部变量操作数栈返回结果。更关注程序方法的执行。
可见度
堆对于整个应用程序共享、可见。
栈只对于线程可见线程私有。生命周期和线程相同。
1.2.2 队列和栈的区别
队列入队出队栈进栈出栈。队列是队尾入队队头出队先进先出两边都可操作栈是先进后出进栈出栈都在栈顶进行。
1.2.3 对象的创建过程
虚拟机收到new指令先检查常量池是否已加载对应的类如果没有先执行相应的类加载java文件转class存入运行时数据区类加载通过后分配内存若堆中的内存是绝对规整的使用“指针碰撞”方式分配内存。若不是规整的从空闲列表中分配。
1.2.4 内存溢出异常
不再被使用的对象或变量一直被占据在内存中。理论上Java有GC垃圾回收机制不再被使用的对象会被GC自动回收。但还是存在内存泄漏问题。
原因长生命周期的对象持有短生命周期对象的引用就会导致内存泄漏。
2 垃圾收集器
2.1 垃圾回收机制
Java中由虚拟机自行执行对象的内存释放。有一个垃圾回收线程低优先级在虚拟机空闲或当前堆内促不足时触发执行扫描那些没有被任何引用的对象并将它们添加到需要回收的集合中进行回收。
2.2 GC
Gabage Collection 垃圾收集忘记或错误的内存回收会导致程序或系统的不稳定甚至崩溃。
Java提供的GC功能可以自动检测对象是否超过作用域从而达到自动回收内存的目的。
垃圾回收的优点
编写程序时不需要考虑内存管理问题Java中的对象不再有“作用域”的概念只有引用的对象才有“作用域”垃圾回收机制有效防止了内存泄漏有效的使用可使用的内存作为一个单独的低级别的线程运行在不可预知的情况下对堆中已经死亡或长时间没有用过的对象进行清除和回收程序员不能实时对某个对象或所有对象调用垃圾回收器进行回收垃圾回收有分代复制、标记、增量垃圾回收
垃圾回收基本原理
对于GC来说当对象被创建后GC就开始监控这个对象的地址、大小、及使用情况。
通常GC采用向图的方式记录和管理堆中的对象。通过确定哪些对象是“可达的”。当GC确定一些对象为“不可达”时GC就有责任回收这些内存空间。
可以通过System.gc()通知GC运行但并不保证GC一定会运行。
怎么判断对象是否可以被回收
引用计数器法为每个对象创建一个引用计数有对象引用时1引用被释放时-1当计数器为0时就可以回收了。但是不能解决循环引用的问题可达性分析算法GC Roots开始向下搜索当一个对象到GC Roots没有任何引用链相连时则证明可以被回收
2.3 垃圾回收算法
标记-清除法标记无用的对象进行清除。其他算法几乎都是在其上进行改进
优点实现简单不需要对象进行移动。
缺点效率低产生大量不连续的内存碎片提高了垃圾回收的频率。
标记阶段标记出可以回收的对象清除阶段回收被标记的对象所占用的空间
复制算法将内存划分为两个相等的区域每次只使用其中一个。每次遍历单个区域将存活的对象复制到另一个区域再清除当前区域。
优点按顺序分配内存运行效率高不用考虑内存碎片
缺点可用的内存大小只要原来的一半对存活率高的对象频繁复制
标记-整理算法在新生代可以使用复制算法老年代不适合存活频率高。标记整理算法在标记回收对象后将所有存活的对象压缩到内存的一段紧凑排列再对边界外的内存进行回收。
优点解决了标记清理算法存在内存碎片的问题
缺点仍需要进行局部的对象移动一定程度上降低了效率
分代收集算法根据对象存活周期将内存划分为几块年轻代、老年代、永久代。jdk1.8后删除了永久代增加了元数据区
2.4 垃圾回收器 Serial收集器复制算法新生代单线程收集器标记和清理都是单线程优点是简单高效。收集器回收时会暂停业务线程。
ParNew收集器复制算法新生代并行收集器Serial收集器的多线程版本多核CPU环境下比Serial性能更好。GC线程和业务线程并行。
Parallel Scavenge复制算法新生代并行收集器追求高吞吐量高效利用CPU。尽快完成程序的运算任务。jdk1.8默认收集器。GC线程和业务线程并行。
Serial Old收集器 标记-整理算法老年代单线程收集器Serial收集器的老年代版本。收集器回收时会暂停业务线程。
Parallel Old收集器标记-整理算法老年代并行收集器吞吐量优先Parallel Scavenge的老年代版本。jdk1.8默认收集器。GC线程和业务线程并行。
CMS收集器标记-清除算法老年代并行收集器以获取最短回收停顿时间为目标的收集器高并发、低停顿追求最短GC回收停顿时间。牺牲了吞度量来获得最短的停顿时间适用于服务器响应速度高要求的应用上。因为是基于标记-清除算法会出现大量内存碎片此时CMS会临时采用Serial Old回收器进行垃圾清除同时性能会下降。GC线程和业务线程并行。在启动 JVM 的参数加上“-XX:UseConcMarkSweepGC”来指定使用 CMS 垃圾回收器。
G1收集器标记-整理算法Java堆并行收集器由jdk1.7提供基于标记整理-算法回收范围为整个堆而不再分新生代和老年代。区域上使用了分区算法。一边清理一部分区域一边占用一部分区域特别大的对象放Humongous区域也不够了开始FullGC。
ZGC颜色算法分区更灵活逻辑上部分带。每次找到特别满的区域进行清除。
垃圾回收器工作流程
新生代:老年代1:2
新生代使用复制-算法本身也分三个区Eden、To Survivor、From Survivor。默认8:1:1
EdenFrom Survivor存活的对象放入To Survivor清空EdenFrom Survivor分区From Survivor和To Survivor分区交换
每次在 From Survivor 到 To Survivor 移动时都存活的对象年龄都1当年龄达到15默认的时升级为老年代大的对象直接放入老年代。
老年代这边当空间占用达到某一个阈值之后触发Full GC此时一般使用标记整理算法。
对象优先分配到新生代的Eden区Eden区空间不够时进行Minor GC还不够则分配到老年代。
Minor GC非常频繁回收速度也快。大对象需要大量连续内存空间的对象直接进入老年代。
3、虚拟机类加载机制
3.1 简述
虚拟机把描述类的数据从class文件加载到内存并对数据进行校验、解析和初始化最终形成虚拟机可以直接使用的Java类型。
3.2 JVM加载Class文件的原理机制
隐式装载程序运行过程中碰到new等方式创建对象时调用类装载器加载对应类到JVM中。
显示装载通过class.forname()等方法显示加载需要的类。
动态加载保证基类完全加载其他类需要的时候才加载。
3.3 类加载器
实现通过类的权限定名获取该类的二进制字节流的代码块
启动类加载器加载Java核心类库无法被程序直接引用。Java_HOME/lib/目录中的被 -Xbootclasspath参数指定路径的类库。扩展类加载器加载Java的扩展库Java虚拟机的实现会提供一个扩展库目录。JDK的安装目录的jre/lib/ext子目录扩展目录或Java. ext. dirs系统变量指定的路径中的所有类库。系统类加载器根据Java应用的类路径ClassPath来加载Java类。通常Java应用的类都是它加载的。可通过ClassLoader.getSystemClassLoader()获取它。用户自定义类加载器通过继承java.lang.ClassLoader类实现。
3.4 类装载的过程
加载根据路径找到对应的class文件导入。验证检查加载的class文件的正确性。准备给类中的静态变量分配内存空间。解析虚拟机将常量池中的符号引用替换成直接引用的过程。初始化对静态变量和静态代码块执行初始化工作。
3.5 双亲委派
如果一个类加载器收到了类加载的请求首先不会自己去加载
而是委派给父类加载器这样所有的加载请求都会传到顶层的启动类加载器
当父加载无法完成加载搜索范围中没找到时子加载器才去尝试加载。
启动类加载器》扩展类加载器》系统类加载器》自定义类加载器。
3.5.1 优点
避免类重复加载唯一性只会在一个类加载器加载。安全性保证Java核心类库的安全比如自己又写了一个java.lang.String优先会去加载核心类库中的。为模块化开发提供了基础支持如果使用多个第三方库可能存在同名的类。使用双亲委派机制可以保证不同的类加载器只加载自己的类避免类名冲突。
4、JVM调优
4.1 工具
JDK的bin目录下自带了很多监控工具。
jconsole用于对JVM中内存、线程和类等进行监控。
jvisualvm内存快照、线程快照、程序死锁、监控内存变化、GC变化等。
4.2 参数
-Xms2g初始化推大小为 2g-Xmx2g堆最大内存为 2g-XX:NewRatio4设置年轻的和老年代的内存比例为 1:4-XX:SurvivorRatio8设置新生代 Eden 和 Survivor 比例为 8:2–XX:UseParNewGC指定使用 ParNew Serial Old 垃圾回收器组合-XX:UseParallelOldGC指定使用 ParNew ParNew Old 垃圾回收器组合-XX:UseConcMarkSweepGC指定使用 CMS Serial Old 垃圾回收器组合-XX:PrintGC开启打印 gc 信息-XX:PrintGCDetails打印 gc 详细信息。 urvivor 比例为 8:2–XX:UseParNewGC指定使用 ParNew Serial Old 垃圾回收器组合-XX:UseParallelOldGC指定使用 ParNew ParNew Old 垃圾回收器组合-XX:UseConcMarkSweepGC指定使用 CMS Serial Old 垃圾回收器组合-XX:PrintGC开启打印 gc 信息-XX:PrintGCDetails打印 gc 详细信息。