大厂春招面试题(二)JVM

         当应聘服务器方面的职位的时候面试官好像很在乎JVM方面掌握的程度,博主主修移动开发,这方面不甚精通,先整理一下相关面试题,方便大家准备。


1.  内存模型以及分区,需要详细到每个区放什么。 

程序计数器:当前线程执行的字节码的行号指示器,线程私有

JAVA虚拟机栈:Java方法执行的内存模型,每个Java方法的执行对应着一个栈帧的进栈和出栈的操作。 

本地方法栈:类似“ JAVA虚拟机栈”,但是为native方法的运行提供内存环境。JAVA:对象内存分配的地方,内存垃圾回收的主要区域,所有线程共享。可分为新生代,老生代。 

方法区:用于存储已经被JVM加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。Hotspot中的“永久代”。 

运行时常量池:方法区的一部分,存储常量信息,如各种字面量、符号引用等。  直接内存:并不是JVM运行时数据区的一部分, 可直接访问的内存, 比如NIO会用到这部分。

2.  堆里面的分区:Eden,survivalfrom to,老年代,各自的特点。 

3.  对象创建方法,对象的内存分配,对象的访问定位。 

4.  GC的两种判定方法:引用计数与引用链。

引用计数方式最基本的形态就是让每个被管理的对象与一个引用计数器关联在一起,该计数器记录着该对象当前被引用的次数,每当创建一个新的引用指向该对象时其计数器就加1,每当指向该对象的引用失效时计数器就减1。当该计数器的值降到0就认为对象死亡。 

Java的内存回收机制可以形象地理解为在堆空间中引入了重力场,已经加载的类的静态变量和处于活动线程的堆栈空间的变量是这个空间的牵引对象。这里牵引对象是指按照Java语言规范,即便没有其它对象保持对它的引用也不能够被回收的对象,即Java内存空间中的本原对象。当然类可能被去加载,活动线程的堆栈也是不断变化的,牵引对象的集合也是不断变化的。对于堆空间中的任何一个对象,如果存在一条或者多条从某个或者某几个牵引对象到该对象的引用链,则就是可达对象,可以形象地理解为从牵引对象伸出的引用链将其拉住,避免掉到回收池中

5.  GC的三种收集方法:标记清除、标记整理、复制算法的原理与特点,分别用在什么地方,如果让你优化收集方法,有什么思路? 

标记清除算法是最基础的收集算法,其他收集算法都是基于这种思想。标记清除算法分为“标记”和“清除”两个阶段:首先标记出需要回收的对象,标记完成之后统一清除对象。它的主要缺点:①.标记和清除过程效率不高。②.标记清除之后会产生大量不连续的内存碎片。 

标记整理,标记操作和“标记-清除”算法一致,后续操作不只是直接清理对象,而是在清理无用对象完成后让所有存活的对象都向一端移动,并更新引用其对象的指针。主要缺点:在标记-清除的基础上还需进行对象的移动,成本相对较高,好处则是不会产生内存碎片。 

复制算法,它将可用内存容量划分为大小相等的两块,每次只使用其中的一块。当这一块用完之后,就将还存活的对象复制到另外一块上面,然后在把已使用过的内存空间一次理掉。这样使得每次都是对其中的一块进行内存回收,不会产生碎片等情况,只要移动堆订的指针,按顺序分配内存即可,实现简单,运行高效。主要缺点:内存缩小为原来的一半。

6.  GC收集器有哪些?CMS收集器与G1收集器的特点。 

单线程收集器,使用单线程去完成所有的gc工作,没有线程间的通信,这种方式会相对高效 

并行收集器,使用多线程的方式,利用多CUP来提高GC的效率,主要以到达一定的吞吐量为目标 

并发收集器,使用多线程的方式,利用多CUP来提高GC的效率,并发完成大部分工作,使得gc pause短 

G1具备如下特点:并行与并发、分代收集、空间整合、可预测的停顿 

CMS具备了并发收集、低停顿的优点、CMS收集器对CPU资源非常敏感、CMS收集器无法处理浮动垃圾、收集结束时会产生大量空间碎片

7.  Minor GC与Full GC分别在什么时候发生? 

Minor GC:通常是指对新生代的回收。指发生在新生代的垃圾收集动作,因为 Java 对象大多都具备朝生夕灭的特性,所以 Minor GC 非常频繁,一般回收速度也比较快

Major GC:通常是指对年老代的回收。

Full GC:Major GC除并发gc外均需对整个堆进行扫描和回收。指发生在老年代的 GC,出现了 Major GC,经常会伴随至少一次的 Minor GC(但非绝对的,在 ParallelScavenge 收集器的收集策略里就有直接进行 Major GC 的策略选择过程)。MajorGC 的速度一般会比 Minor GC 慢 10倍以上。

8. 几种常用的内存调试工具:jmap、jstack、jconsole。 

9. 类加载的五个过程:加载、验证、准备、解析、初始化。

 “加载”(Loading)阶段是“类加载”(ClassLoading)过程的第一个阶段,在此阶段,虚拟机需要完成以下三件事情: 

1、 通过一个类的全限定名来获取定义此类的二进制字节流。 

2、 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。

3、 在Java堆中生成一个代表这个类的java.lang.Class对象,作为方法区这些数据的访问入口。

验证是连接阶段的第一步,这一阶段的目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。 

准备阶段是为类的静态变量分配内存并将其初始化为默认值,这些内存都将在方法区中进行分配。准备阶段不分配类中的实例变量的内存,实例变量将会在对象实例化时随着对象一起分配在Java堆中。 

解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。

类初始化是类加载过程的最后一步,前面的类加载过程,除了在加载阶段用户应用程序可以通过自定义类加载器参与之外,其余动作完全由虚拟机主导和控制。到了初始化阶段,才真正开始执行类中定义的Java程序代码

10. 双亲委派模型:Bootstrap ClassLoader、Extension ClassLoader、ApplicationClassLoader。 

11. 分派:静态分派与动态分派。 

静态分派与重载有关,虚拟机在重载时是通过参数的静态类型,而不是运行时的实际类型作为判定依据的;静态类型在编译期是可知的;

动态分派与重写(Override)相关,invokevirtual(调用实例方法)指令执行的第一步就是在运行期确定接收者的实际类型,根据实际类型进行方法调用;

 


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值