Java面试-JVM(Java虚拟机)

JVM的主要组成部分及作用

JVM由两个子系统和两个组件组成
子系统分别是类加载器和执行引擎

  • 类加载器:加载.class文件到JVM的内存中
  • 执行引擎负责执行classes中的指令
    组件分别是运行时数据区和本地方法接口
  • 运行时数据区就是JVM的内存
  • 本地方法接口就是和本地方法交互的接口

堆栈的区别

  • 堆存放一些对象,栈存放局部变量表,操作数栈,动态链接,方法返回值
  • 堆占用的内存比栈大
  • 堆只能动态分配,栈支持静态分配和动态分配
  • 堆需要GC,栈不需要,执行完方法就会弹出栈,清空
  • 堆是线程共享的,栈是线程私有的

队列和栈的区别

  • 队列先进先出,栈后进先出

Java什么时候会出现内存泄漏

Java垃圾回收机制

Java进行垃圾回收是在堆中进行,堆分为年轻代和老年代,
年轻代又分为一个eden区和两个survivor区,默认比例为8:1:1,survivor又分为from区和to区,刚开始对象在eden区和from区进行对象分配,当发生GC的时候,eden区存活的对象会存放到to区,from区的对象会根据年龄判断存放到to区还是老年代,如果年龄大于15,则放到老年代,一些大的对象直接放到老年代,当GC完成之后,from和to进行交换,此时from区就变成了to区,to区就变成了from区

GC是什么.为什么需要GC

GC就是垃圾回收的意思,如果没有GC的话堆内存满了之后就可能发生内存泄漏,内存溢出

强软弱虚

强引用:不会被垃圾收集的一些对象,也就是我们new的对象
软引用:在发生内存溢出之前会被回收
弱引用:在发生GC之前会被回收的对象
虚引用:无论发不发生gc都会被回收

怎么判断垃圾是否被回收

判断垃圾回收有两种办法

  • 第一种就是引用计数法,通过判断对象引用的次数来判断对象是否被回收,当我们引用一个对象时会有一个引用计数器,引用一次,引用计数器加一,引用完成之后,引用计数器减一,当引用计数器为0的时候,此时对象就可以视为垃圾,但是这种方法有一个弊端,就是当我们循环引用的时候,引用计数器永远不可能为0,就可能会导致内存泄漏
  • 第二种方法就是可达性分析法,通过判断对象的引用链来判断对象是否被回收,从GCroot开始向上寻找对象引用的节点,一直寻找完成,看看有哪些对象是没有被引用的,这些对象就可以视为垃圾

永久代会发生垃圾回收吗

不会,永久代满了之后直接发生FullGC

有哪些垃圾回收算法

  • 标记-清除算法:在堆中对对象进行遍历,对存活的对象进行标记,然后清除不可达的对象,这种方式会产生大量的垃圾碎片,不利于以后大对象的存储
  • 复制算法:首先将堆分为一个对象面和一个空闲面,对象在对象面进行对象分配,然后将对象面存活的对象复制到空闲面,然后此时空闲面就变成了对象面,对象面就变成了空闲面,这种方式会浪费一般的内存空间
  • 标记-整理算法:在堆中对对象进行遍历,标记存活的对象,然后对存活的对象进行排序,依次放入内存中,把尾结点之后的空间清除,这种方式会进行大量的对象的移动
  • 分代回收算法:就是上面三种的整合,按需操作,在年轻代由于对象存活率比较低,所以使用复制算法,老年代对象存活率比较高,所以使用标记-清除,标记整理算法

有哪些垃圾收集器

年轻代:serial ,ParNew, Parallel Scavenge
老年代:serial old , ParallelOld,CMS

介绍一下CMS垃圾回收器

待续

分代垃圾回收怎么工作

Java进行垃圾回收是在堆中进行,堆分为年轻代和老年代,
年轻代又分为一个eden区和两个survivor区,默认比例为8:1:1,survivor又分为from区和to区,刚开始对象在eden区和from区进行对象分配,当发生GC的时候,eden区存活的对象会存放到to区,from区的对象会根据年龄判断存放到to区还是老年代,如果年龄大于15,则放到老年代,一些大的对象直接放到老年代,当GC完成之后,from和to进行交换,此时from区就变成了to区,to区就变成了from区

老年代采用标记清除算法和标记整理算法进行垃圾回收

内存分配策略和Minor GC和Major GC

MinorGC发生在年轻代,上一题已经详细介绍,Major发生代老年代,当永久代空间满了,或者老年代空间不足,或者我们手动system.gc()就会触发FullGC

类加载过程

类加载的过程分为三步

  • 加载:通过类加载器将.class文件加载到JVM的内存中
  • 链接:校验-校验.class文件的安全性和正确性
    准备-给静态变量分配内存空间,如果静态变量是final修 饰的,则直接赋值
    解析-将符号引用转化为直接引用
  • 初始化:加载静态代码块,给静态变量赋值

类加载器是什么,有哪些

类加载器就是负责加载.class文件到JVM的内存中
类加载器有四种,从上到下依次是:

  • 初始类加载器:加载核心类
  • 扩展类加载器:加载扩展的jar包
  • 应用程序类加载器:加载classpath下面指定的内容
  • 自定义类加载器:加载自定义的jar

描述一下JVM加载Class文件的原理和机制

JVM加载class文件有两种方式,显示加载和隐式加载
显示加载:使用Class.forName或者classloader实现
隐式加载:当我们new一个对象时候,就会使用隐式加载

双亲委派机制

双亲委派机制就相当于类加载器的一个空间模型

  • 初始类加载器:加载核心类
  • 扩展类加载器:加载扩展的jar包
  • 应用程序类加载器:加载classpath下面指定的内容
  • 自定义类加载器:加载自定义的jar

当类加载器收到一个加载类的请求时候,首先类加载器不会自己尝试去加载,就会将这个请求向上抛,最终都会到根类加载器上,只有当父类加载器反馈无法加载这个类的时候,子类加载器才会尝试去加载,双亲委派机制的好处就是通过一层层向上,看看哪个类加载过这个.class文件,能够避免重复加载,可以进行按需加载

说一下JVM调优工具

jconsole
jvisualvm

常用的JVM调优参数有哪些

  • -Xms2g:初始化堆大小为2g
  • -Xmx2g:堆最大内存为2g
  • -XX:NewRatio=4:设置年轻代和老年代的比例为1:4
  • -XX:+PrintGC:开启打印GC信息
  • -XX:+PrintGCDetails:打印GC详细信息

猜你喜欢

转载自blog.csdn.net/weixin_44219219/article/details/112823627