青岛乾程&济南中孚Java面经&JVM垃圾回收


前言

愿你有一个令自己满意的offer
下文所提到的二面一。是指两位面试官面试你,其中一个是技术面,两家均是一男一女


一、关于乾程(都开了摄像头,都很面善友好)

1.HR闲聊

  1.技术面和HR面一次性进行(总时长15—20min)
  2.HR面:自我介绍、有没有挂过科、专业名次、获得奖项、、、有没有了解过我们公司(一定要提前了解)、
  切记这届公司好面:
  			1.一定要提前了解这家公司,不要让二者觉得你是“海投”,
  			2.你可以喜欢打羽毛球,因为技术面试官也喜欢(会问你用什么球拍)

2.技术面

3.技术面:(整合了多为同学的面试问题几乎所有的问题都是一句话解决)几乎没有数据结构计操计网 
1)面向对象三大特性:答一句话就可以,:封装、继承、多态
2)怎么实现多态:多态一定离不开继承,实现方式主要是可以将子类实例化的对象赋值给父类类型的变量,在运行时针对不同情况对父类的方法的重写,对自己方法的重载。
3)DDL、DML的区别:
	DML(Data Manipulation Language)数据操纵语言:
	对数据库中的数据进行一些简单操作,如insert,delete,update,select等.
	DDL(Data Definition Language)数据定义语言:
	对数据库中的某些对象(例如,database,table)进行管理,如Create,Alter和Drop.
4)数据库三范式:
	第一范式原子性:数据表中字段值不可再分割
	第二范式唯一性:消除非主键部分对联合主键中部分字段的依赖
	第三范式独立性:消除传递依赖(不能存在非主键值依赖非主键值)
5)请你说说Spring的核心是什么
	IOC、AOP(无需多言,技术面自然会继续下去)
6)详细说说AOP(IOC依赖注入都会说,所以就不问了)
6)反射的理解【专业技能里面“反射”二字加粗了】
7)String a="";String b =null;的区别、、你可以再去了解String c = new String("");和前面二者的区别
8)servlet的作用--那20个字
9)拦截器与过滤器谁先执行(过滤器包裹servlet,servlet包裹住拦截器)---过滤器先执行
11)spring 与 springboot的区别
12)laypage 项目中分页的实现

3.HR继续问收尾+反问

1.面试常见问题:能否接受加班、对加班的看法
1.面试官你好  暂时是这么考虑的:首先刚出校园加入规矩公司,自知不足、熟悉贵公司制度、软件开发不断学习、我希望进入贵公司的核心开发团队,1-2年。。。
带领项目开发团队,
我的终极目标是  架构师
还请面试官指正

二、关于中孚(有个宗旨)(对方均未开了摄像头,小姐姐声音好听)

1.直接技术面(大多反应被问得头皮发麻–)

宗旨:一定要把你项目中的相关“安全”的想清楚,毕竟这是个注重安全的企业

数据库的安全问题,数据库SQL注入,前端的ajax\jsp安全问题、后端业务层的合理合法性校验、不管什么项目,把项目中的数据安全、线程安全、。。。。

1.简历上面的项目分别描述介绍:主要功能、主要技术、主要负责部分(个人项目,前后端开发)
	(项目中的过滤器、MD5的加密)
	2.项目开发的难点,碰上的问题
	3.SQL注入问题怎么解决
	4.是否熟悉linux的简单命令(重点)-》公司使用linux
	5.代码版本控制工具
	8.cookies\session区别
	9.操作系统:磁盘调度算法
	10.三握四挥了解,接着:详细说说四挥,-把第三次挥手去掉会怎么样-
	11.四次挥手的最后一步2msl是什么意思,1msl行不行、3msl行部行
	13。数据库:使用过索引吗---》讲一下索引
	14。jvm:GC回收算法————》
	15.怎么判断对象是个垃圾--》
	15.说说对信息安全的认识===对一个项目提出整套的安全解决方案
	16.servlet\JSP二者区别

2.HR小姐姐闲聊时间

	6.职业规划:
	7.HR:了解公司吗

总结

下文是参考牛客的评论区(如有需要请私聊删除)【也做了补充】

垃圾回收包含的内容不少,但顺着下面的顺序捋清知识也并不难。

  • 首先要 搞清垃圾回收的范围(栈需要GC去回收吗?,很明显不需要)

  • 然后就是回收的前提条件: 如何判断一个对象(已经)可以被回收(这里只重点学习根搜索算法就行了)

  • 之后便是建立在根搜索基础上的三种回收策略

  • 最后便是JVM中对这三种策略的具体实现。
    1.范围:要回收哪些区域?

    方法区:是线程共享的内存区域,用来存储类加载的信息、常量、静态变量、即时编译器编译后的代码等。其中方法区中还有个经常会用到的区域叫做运行时常量池,主要用于存储一些常量,当创建一个常量时,首先会在运行时常量池查看是否有,有则直接使用,否则重新创建。
    是最大的一块内存区域,也是垃圾回收管理的主要区域,主要用于存放对象实例。
    程序计数器:线程私有的,每个线程都会分配一个线程计数器,用来表示当前线程执行的字节码的行号指示器。在多线程中,一个线程执行的时候释放锁,另一个线程执行完,再回来执行前面线程的时候,就是通过程序计数器来获取继续执行的位置。
    虚拟机栈(Java栈):虚拟机栈主要存储基本数据类型变量和引用类型变量。其中与堆的区别就是如:Obj obj=new Object();等号左边则是在虚拟机栈上分配栈区存储引用类型变量的句柄Obj obj,等号右边则是存储对象实例,栈区的句柄是指向堆区的对象实例的,一般通过句柄访问堆区的对象实例。
    本地方法栈:与虚拟机栈意义相似,区别在于虚拟机栈用于使Java方法,而本地方法栈则是针对于Native方法服务。

    1.Java方法栈、本地方法栈以及PC计数器随方法或线程的结束而自然被回收,所以这些区域不需要考虑回收问题。
    2.Java堆和方法区是GC回收的重点区域,因为一个接口的多个实现类需要的内存不一样,一个方法的多个分支需要的内存可能也不一样,而这两个区域又对立于栈可能随时都会有对象不再被引用,因此这部分内存的分配和回收都是动态的
    借助这张图理解:
    截取自尚硅谷视频中

    2.前提:如何判断对象已死?
    (1)引用计数法
    引用计数法就是通过一个计数器记录该对象被引用的次数,方法简单高效,但是解决不了循环引用的问题。比如对象A包含指向对象B的引用,对象B也包含指向对象A的引用,但没有引用指向A和B,这时当前回收如果采用的是引用计数法,那么对象A和B的被引用次数都为1,都不会被回收。循环引用在Hotspot JVM下可以被正常回收,可以证实JVM 采用的不是简单的引用计数法
    (2)根搜索(可达性分析算法)
    通过选取一些根(GC Roots)对象作为起始点,开始向下搜索,如果一个对象到根对象不可达时,则说明此对象已经没有被引用,是可能被回收的(为什么说可能,因为可能复活)。(如果可达:那就是一定在被使用)
    可以作为根的对象有:栈中变量引用的对象,类静态属性引用的对象,常量引用的对象等。因为每个线程都有一个栈,所以我们需要选取多个根对象。在根搜索中得到的不可达对象并不是立即就被标记成可回收的,而是先进行一次标记放入F-Queue等待执行对象的finalize()方法,执行后GC将进行二次标记,复活的对象之后将不会被回收。因此,使对象复活的唯一办法就是重写finalize()方法,并使对象重新被引用。

代码附:对象复活示例

public class DeadToRebirth {  
       private static DeadToRebirth hook;   
       @Override
       public void finalize() throws Throwable {  
       		super.finalize(); 
            DeadToRebirth.hook = this; 
       }
       public static void main(String[] args) throws Exception {  
            DeadToRebirth.hook = new DeadToRebirth();  
            DeadToRebirth.hook = null;  
            System.gc();  
            Thread.sleep(500);  
            if (DeadToRebirth.hook != null)  
            System.out.println("Rebirth!");  
               else  
                  System.out.println("Dead!");  
            DeadToRebirth.hook = null;  
            System.gc();  
            Thread.sleep(500);  
            if (DeadToRebirth.hook != null)  
              System.out.println("Rebirth!");  
            else  
              System.out.println("Dead!");  
          }    
      }  

要注意的两点是:
第一,finalize()方法只会被执行一次,所以对象只有一次复活的机会。
第二,执行GC后,要停顿半秒等待优先级很低的finalize()执行完毕。

如果没有复活那就是——彻底死亡:(就涉及到:标记整理、标记清除、复制(三个实际算法,当然还有两个思想,但还没有真正实现,所以你面试时可以说三个,可以说五个))
3.策略:垃圾回收的算法

(1)标记-清除

没错,这里的标记指的就是之前我们介绍过的两次标记过程
[第一次标记放入F-Queue等待执行对象的finalize()方法,执行后GC将进行二次标记]。
标记完成后就可以对标记为垃圾的对象进行回收了。
怎么样,简单吧。但是这种策略的缺点很明显,
回收后内存碎片很多,如果之后程序运行时申请大内存,可能会又导致一次GC。虽然缺点明显,这种策略却是后两种策略的基础。正因为它的缺点,所以促成了后两种策略的产生。

(2)标记-复制

将内存分为两块,标记完成开始回收时,将一块内存中保留的对象全部复制到另一块空闲内存中。实现起来也很简单,当大部分对象都被回收时这种策略也很高效。
但这种策略也有缺点,可用内存变为一半了!
怎样解决呢?可以将堆(Heap)不按1:1的比例分离,而是按8:1:1分成一块Eden和两小块Survivor区,每次将Eden和Survivor中存活的对象复制到另一块空闲的Survivor中。

图片来源:牛客另一个评论区
值得注意的是:1.8之后没有了永久代(持久代),而是使用元空间
这三块区域并不是堆的全部,而是构成了堆的新生代。从图可以看到这三块区域如何配合完成GC的,具体的对象空间分配以及晋升请看后面第6条补充。
为什么不是堆的全部呢?如果回收时,空闲的那一小块Survivor不够用了怎么办?这就是老年代的用处。当不够用时,这些对象将直接通过分配担保机制进入老年代。
那么老年代也使用标记-复制策略吧?当然不行!老年代中的对象可不像新生代中的,每次回收都会清除掉大部分。如果贸然采用复制的策略,老年代的回收效率可想而知。
根据老年代的特点,采用回收掉垃圾对象后对内存进行整理的策略再合适不过,将所有存活下来的对象都向一端移动。

(3)标记-整理

4.具体实现:虚拟机中的收集器

(1)新生代上的GC实现

Serial:单线程的收集器,只使用一个线程进行收集,并且收集时会暂停其他所有工作线程(Stop the world)。它是Client模式下的默认新生代收集器。
ParNew:Serial收集器的多线程版本。在单CPU甚至两个CPU的环境下,由于线程交互的开销,无法保证性能超越Serial收集器。
Parallel Scavenge:也是多线程收集器,与ParNew的区别是,它是吞吐量优先收集器。**吞吐量=运行用户代码时间/(运行用户代码+垃圾收集时间)。**另一点区别是配置-XX:+UseAdaptiveSizePolicy后,虚拟机会自动调整Eden/Survivor等参数来提供用户所需的吞吐量。我们需要配置的就是内存大小-Xmx和吞吐量GCTimeRatio。

(2)老年代上的GC实现

Serial Old:Serial收集器的老年代版本。
Parallel Old:Parallel Scavenge的老年代版本。此前,如果新生代采用PS GC的话,老年代只有Serial Old能与之配合。现在有了Parallel Old与之配合,可以在注重吞吐量及CPU资源敏感的场合使用了。
CMS:采用的是标记-清除而非标记-整理,是一款并发低停顿的收集器。但是由于采用标记-清除,内存碎片问题不可避免。可以使用
-XX:CMSFullGCsBeforeCompaction 设置执行几次CMS回收后,跟着来一次内存碎片整理。
5.触发:何时开始GC?
Minor GC(新生代回收)的触发条件比较简单,Eden空间不足就开始进行Minor GC回收新生代。
而Full GC(老年代回收,一般伴随一次Minor GC)则有几种触发条件:
(1)老年代空间不足
(2)PermSpace空间不足
(3)统计得到的Minor GC晋升到老年代的平均大小大于老年代的剩余空间
这里注意一点:PermSpace并不等同于方法区,只不过是Hotspot JVM用PermSpace来实现方法区而已,有些虚拟机没有PermSpace而用其他机制来实现方法区。
6.补充:对象的空间分配和晋升

(1)对象优先在Eden上分配
(2)大对象直接进入老年代
虚拟机提供了-XX:PretenureSizeThreshold参数,大于这个参数值的对象将直接分配到老年代中。因为新生代采用的是标记-复制策略,在Eden中分配大对象将会导致Eden区和两个Survivor区之间大量的内存拷贝。
(3)长期存活的对象将进入老年代
对象在Survivor区中每熬过一次Minor GC,年龄就增加1岁,当它的年龄增加到一定程度 *默认为15岁)*时,就会晋升到老年代中。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值