0
点赞
收藏
分享

微信扫一扫

【面经】JVM零散整理

Aliven888 2022-03-12 阅读 152
java面试

From: JVM 系列阅读笔记:https://liudongdong1.github.io/tags/jvm/

.1. 简述垃圾回收机制
.2. 内存模型

  • Java 堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。
  • 方法区(Method Area)是各个线程共享的内存区域,它用于存储已被虚拟机加载类信息、常量、静态变量、即时编译器编译后的代码等数据。
  • 程序计数器(Program Counter Register)是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器
  • Java 虚拟机栈(Java Virtual Machine Stacks)也是线程私有的,它的生命周期与线程相同。虚拟机栈描述的是 Java 方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧(Stack Frame)用于存储局部变量表、操作栈、动态链接、方法出口等信息。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
  • 本地方法栈(Native Method Stacks)与虚拟机栈所发挥的作用是非常相似的,其区别不过是虚拟机栈为虚拟机执行 Java 方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的 Native 方法服务。
.3. 如何判断对象死完:
.4. GC 回收机制
1. 标记清除法:
2. 复制算法:
3. 标记整理算法
4. 分代收集算法

当前商业虚拟机都采用分代收集的垃圾收集算法。分代收集算法,顾名思义是根据对象的存活周期将内存划分为几块。一般包括年轻代老年代永久代,如图所示:

.5.垃圾回收三色标记法:
.6. CMS垃圾回收器介绍:
.7. JVM 俩个内存
1. 栈内存
2. 堆内存
.8. 类加载器
  • 启动类加载器:Bootstrap ClassLoader,负责加载存放在 JDK\jre\lib (JDK 代表 JDK 的安装目录,下同) 下,或被 - Xbootclasspath 参数指定的路径中的,并且能被虚拟机识别的类库
  • 扩展类加载器:Extension ClassLoader,该加载器由 sun.misc.Launcher$ExtClassLoader 实现,它负责加载 DK\jre\lib`ext 目录` 中,或者由 java.ext.dirs 系统变量指定的路径中的所有类库(如 javax.* 开头的类),开发者可以直接使用扩展类加载器。
  • 应用程序类加载器:Application ClassLoader,该类加载器由 sun.misc.Launcher$AppClassLoader 来实现,它负责加载用户类路径(ClassPath)所指定的类,开发者可以直接使用该类加载器
    • 避免重复加载 + 避免核心类篡改

.2. 加载机制
  • 全盘负责: 当一个类加载器负责加载某个 Class 时,该Class所依赖的和引用的其他Class也将由该类加载器负责载入,除非显示使用另外一个类加载器来载入。
  • 缓存机制: 缓存机制将会保证所有加载过的Class都会被缓存,当程序中需要使用某个 Class 时,类加载器先从缓存区寻找该Class,只有缓存区不存在,系统才会读取该类对应的二进制数据,并将其转换成Class对象,存入缓存区。这就是为什么修改了 Class 后,必须重启 JVM,程序的修改才会生效。
  • 双亲委派机制: 如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到最顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去完成加载。

.9. 对象创建

.10. 对象内存分布

.11. OutofMemory错误
.12. Full GC
.12. 拷贝
  • 浅拷贝:如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址
  • 深拷贝:会拷贝所有的属性,并拷贝属性指向的动态分配的内存. 可以使用 Arrays.copyof ()
.13. 反射
  • 是 JVM 在运行时动态加载类,调用方法或者访问属性,不需要知道运行对象是谁
  • 相关的类:
    • class: 每一个类都有一个 class 对象(类实例),包含类的相关信息
    • Field:使用 get/set 修改或者读取 Field 相关对象
    • method:使用 invoke方法调用与method相关联的对象
    • Constructor: 使用 newInstance () 构建对象
    • Object 类:Object 是所有 Java 类的父类。所有对象都默认实现了 Object 类的方法。
.14. 如何避免内存泄漏
  • 未对作废数据内存单元置为 null
  • 尽早释放无用对象的引用,
  • 使用临时变量时,让引用变量在推出活动域后自动设置为 null,暗示垃圾收集器收集;
  • 程序避免用 String 拼接,用 StringBuffer,因为每个 String 会占用内存一块区域;
  • 尽量少用静态变量(全局不会回收);
  • 不要集中创建对象尤其大对象,可以使用流操作;
  • 尽量使用对象池,不再循环中创建对象,优化配置;
  • 创建对象到单例 getInstance 中,对象无法回收被单例引用;
  • 服务器 session 时间设置过长也会引起内存泄漏。
.15. 检查异常&运行时异常
  • 检查异常是在程序中最经常碰到异常,所有继承自 Exception 并且不是运行时异常的异常都是检查异常,比如咱们最常见的 IO 异常和 SQL 异常。这种异常都发生在编译的阶段,Java 编译器强制程序去捕获此类型的异常,即它会把可能会出现这些异常的代码放到 try 块中,把对异常的处理代码放到 catch 块中。受检异常跟程序运行的上下文环境有关,即使程序设计无误,仍然可能因使用的问题而引发。

  • 运行时异常不同于检查异常,编译器没有强制对其进行捕获并处理,如果不对异常进行处理,那么当出现这种异常的时候,会由 JVM 来处理,比如 NullPointerException 异常,它就是运行时异常。只要程序设计得没有问题通常就不会发生运行时异常。

举报

相关推荐

0 条评论