互联网的程序员,或许是目前找工作最为频繁的行业了
从去年开始,互联网公司的程序员就面临着比以往更多的工作压力,毕竟程序员拿到的工资也是比较高的,而有些程序员为了寻求更好的工作,只能选择跳槽
但跳槽之后,就一定能够拿到比现在更好的待遇吗?能否拿到更好的待遇还不得而知,在想要顺利的进入新公司,就必须通过第一关:面试
一、线程私有;每个方JVM常用参数
JVM主要参数:堆设置、回收器选择(串行、并行、并发收集器)
二、JVM的内存结构
根据 JVM 规范,JVM 内存共分为虚拟机栈、堆、方法区、程序计数器、本地方法栈五个部分。
-
Java虚拟机栈:
法在执行的时候会创建一个栈帧,存储了局部变量表,操作数栈,动态连接,方法返回地址等;每个方法从调用到执行完毕,对应一个栈帧在虚拟机栈中的入栈和出栈。 -
堆:
线程共享;被所有线程共享的一块内存区域,在虚拟机启动时创建,用于存放对象实例。 -
方法区:
线程共享;被所有线程共享的一块内存区域;用于存储已被虚拟机加载的类信息,常量,静态变量等。 -
程序计数器:
线程私有;是当前线程所执行的字节码的行号指示器,每条线程都要有一个独立的程序计数器,这类内存也称为“线程私有”的内存。 -
本地方法栈:
线程私有;主要为虚拟机使用到的Native方法服务。
三、GC的三种收集方法:标记清除、标记整理、复制算法的原理与特点,分别用在什么地方,如果让你优化收集方法,有什么思路?
- 先标记,标记完毕之后再清除,效率不高,会产生碎片
- 复制算法:分为8:1的Eden区和survivor区,就是上面谈到的YGC
-
标记整理:标记完毕之后,让所有存活的对象向一端移动
四、GC收集器有哪些?CMS收集器与G1收集器的特点。
- 并行收集器:串行收集器使用一个单独的线程进行收集,GC时服务有停顿时间
- 串行收集器:次要回收中使用多线程来执行
- CMS收集器是基于“标记—清除” 算法实现的,经过多次标记才会被清除
- G1从整体来看是基于“标记—整理”算法实现的收集器,从局部(两个Region之间)上来看是基于“复制”算法实现的
五、JVM的内存相关,如何实现?
Java堆,Java栈,程序计数器,方法区,1.7的永久代,1.8的metaspace....尽可能多说,顺带简短描述下每个内存区的用途,能想到的都讲出来。
六、几种常用的内存调试工具:
jmap、jstack、jconsole。
七、JVM 年轻代到年老代的晋升过程的判断条件是什么呢
- 部分对象会在From和To区域中复制来复制去,如此交换15次(由JVM参数MaxTenuringThreshold决定,这个参数默认是15),最终如果还是存活,就存入到老年代。
- 如果对象的大小大于Eden的二分之一会直接分配在old,如果old也分配不下,会做一次majorGC,如果小于eden的一半但是没有足够的空间,就进行minorgc也就是新生代GC。
- minor gc后,survivor仍然放不下,则放到老年代
-
动态年龄判断 ,大于等于某个年龄的对象超过了survivor空间一半 ,大于等于某个年龄的对象直接进入老年代
八、JVM垃圾回收机制,何时触发MinorGC等操作
当young gen中的eden区分配满的时候触发MinorGC(新生代的空间不够放的时候).
九、判断一个对象应该被回收
- 该对象没有与GC Roots相连
- 该对象没有重写finalize()方法或finalize()已经被执行过则直接回收(第一次标记)、否则将对象加入到F-Queue队列中(优先级很低的队列)在这里finalize()方法被执行,之后进行第二次标记,如果对象仍然应该被GC则GC,否则移除队列。 (在finalize方法中,对象很可能和其他 GC Roots中的某一个对象建立了关联,finalize方法只会被调用一次,且不推荐使用finalize方法)
十、什么情况下会出现栈溢出
- 方法创建了一个很大的对象,如 List,Array。
- 是否产生了循环调用、死循环。
-
是否引用了较大的全局变量。
十一、对象什么时候进入老年代?
-
对象优先在Eden区分配内存
当对象首次创建时, 会放在新生代的 eden 区, 若没有 GC 的介入,会一直在 eden 区,GC 后,是可能进入 survivor 区或者年老代。 -
大对象直接进入老年代
所谓的大对象是指需要大量连续内存空间的 Java 对象,最典型的大对象就是那种很长的字符串以及数组,大对象对虚拟机的内存分配就是坏消息,尤其是一些朝生夕灭的短命大对象,写程序时应避免。 -
长期存活的对象进入老年代
虚拟机给每个对象定义了一个对象年龄(Age)计数器,对象在 Survivor 区中每熬过一次 Minor GC,年龄就增加 1,当他的年龄增加到一定程度(默认是 15 岁), 就将会被晋升到老年代中。
十二、什么时候触发 Full 行GC ?
- 调用 System.gc 时,系统建议执 Full GC,但是不必然执行。
- 老年代空间不足。
- 方法区空间不足。
- 通过 Minor GC 后进入老年代的平均大小大于老年代的可用内存。
- 由 Eden 区、survivor space1(From Space)区向 survivor space2(To Space)区复制时,对象大小大于 To Space 可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小。
十三、GC的两种判定方法:
-
引用计数法:
指的是如果某个地方引用了这个对象就+1,如果失效了就-1,当为0就会回收但是JVM没有用这种方式,因为无法判定相互循环引用(A引用B,B引用A)的情况 -
引用链法:
通过一种GC ROOT的对象(方法区中静态变量引用的对象等-static变量)来判断,如果有一条链能够到达GC ROOT就说明,不能到达GC ROOT就说明可以回收
十四、类加载的几个过程:
加载、验证、准备、解析、初始化。然后是使用和卸载了
通过全限定名来加载生成class对象到内存中,然后进行验证这个class文件,包括文件格式校验、元数据验证,字节码校验等。准备是对这个对象分配内存。解析是将符号引用转化为直接引用(指针引用),初始化就是开始执行构造器的代码。
十五、一个对象的内存划分是怎样的?
可分为3块区域:对象头,实例数据,对齐填充
- 对象头由Mark world和类型指针组成
mark World包括hash码,GC分代年龄,锁状态标志等。
类型指针来确定这个对象是哪个类的实例 - 实例数据是对象存储的真正的有效信息
- hostspot虚拟机要求对象的大小必须是8字节的整数倍
------完结------
感谢你的阅读,点赞、关注一下再走吧!!!














网友评论