Java问题整理总结

从四月份到五月份面试了很多家公司,现场的去南京也去了五六次,线上的也面了不少,总结一下,现场的面试题比网上的面试题难很多,会涉及很多不同的领域,我的项目经验不是很突出,所以现场的笔试非常重要,记得最多来回考的一点是新建string对象==与equals的判定。现在我已经签了南京一家公司,所以最后做一个总结,总结一些出现频率比较高的问题。

1. JVM参数配置、常用调试工具、分区、类加载、垃圾回收器、垃圾回收算法还会问你有需要线上的调试问题吗?遇到死循环CPU飙升怎么解决(我没怎么被问过,一般招聘要求有具备系统调优、性能调优等技能就会问这些,有需要可以仔细阅读《深入理解Java虚拟机》这一本书)
一、JVM参数配置
1、跟踪参数:跟踪、监控JVM状态,用于程序员JVM调优及故障排查。比如
-XX:+PrintGC 打印GC日志
2、堆分配参数:分配堆内存。比如-Xmx=2g最大堆;-Xms=1g最小堆;-XX:NewRatio=4,则表示新生代:老年代=1:4;-XX:SurvivorRatio=6,则表示Survivor区:Eden区=2:6
3、栈分配参数:分配栈内存
二、常用调试工具
JDK 自带了很多监控工具,都位于 JDK 的 bin 目录下,其中最常用的是 jconsole 和 jvisualvm 这两款视图监控工具。
jconsole:用于对 JVM 中的内存、线程和类等进行监控;
jvisualvm:JDK 自带的全能分析工具,可以分析:内存快照、线程快照、程序死锁、监控内存的变化、gc 变化等。
三、分区
Java问题整理总结
不同虚拟机的运行时数据区可能略微有所不同,但都会遵从 Java 虚拟机规范, Java 虚拟机规范规定的区域分为以下 5 个部分:

程序计数器(Program Counter Register):当前线程所执行的字节码的行号指示器,字节码解析器的工作是通过改变这个计数器的值,来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能,都需要依赖这个计数器来完成;
Java 虚拟机栈(Java Virtual Machine Stacks):用于存储局部变量表、操作数栈、动态链接、方法出口等信息;
本地方法栈(Native Method Stack):与虚拟机栈的作用是一样的,只不过虚拟机栈是服务 Java 方法的,而本地方法栈是为虚拟机调用 Native 方法服务的;
Java 堆(Java Heap):Java 虚拟机中内存最大的一块,是被所有线程共享的,几乎所有的对象实例都在这里分配内存;
方法区(Methed Area):用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据。
四、类加载
类加载机制就是虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验,解析和初始化,最终形成可以被虚拟机直接使用的java类型。实现通过类的权限定名获取该类的二进制字节流的代码块叫做类加载器。类装载分为以下 5 个步骤:

  • 加载:根据查找路径找到相应的 class 文件然后导入;
  • 验证:检查加载的 class 文件的正确性;
  • 准备:给类中的静态变量分配内存空间;
  • 解析:虚拟机将常量池中的符号引用替换成直接引用的过程。符号引用就理解为一个标示,而在直接引用直接指向内存中的地址;
  • 初始化:对静态变量和静态代码块执行初始化工作。
    五、垃圾回收器
    Java问题整理总结
  • Serial收集器(复制算法): 新生代单线程收集器,标记和清理都是单线程,优点是简单高效;
  • ParNew收集器 (复制算法):
    新生代收并行集器,实际上是Serial收集器的多线程版本,在多核CPU环境下有着比Serial更好的表现;
  • Parallel Scavenge收集器 (复制算法): 新生代并行收集器,追求高吞吐量,高效利用 CPU。吞吐量 =用户线程时间/(用户线程时间+GC线程时间),高吞吐量可以高效率的利用CPU时间,尽快完成程序的运算任务,适合后台应用等对交互相应要求不高的场景;
  • Serial Old收集器 (标记-整理算法): 老年代单线程收集器,Serial收集器的老年代版本;
  • Parallel Old收集器 (标记-整理算法): 老年代并行收集器,吞吐量优先,Parallel Scavenge收集器的老年代版本;
  • CMS(Concurrent Mark Sweep)收集器(标记-清除算法):
    老年代并行收集器,以获取最短回收停顿时间为目标的收集器,具有高并发、低停顿的特点,追求最短GC回收停顿时间。
  • G1(Garbage First)收集器 (标记-整理算法):
    Java堆并行收集器,G1收集器是JDK1.7提供的一个新收集器,G1收集器基于“标记-整理”算法实现,也就是说不会产生内存碎片。此外,G1收集器不同于之前的收集器的一个重要特点是:G1回收的范围是整个Java堆(包括新生代,老年代),而前六种收集器回收的范围仅限于新生代或老年代。

新生代垃圾回收器一般采用的是复制算法,复制算法的优点是效率高,缺点是内存利用率低;老年代回收器一般采用的是标记-整理的算法进行垃圾回收。
六、垃圾回收算法

  • 标记-清除算法:标记无用对象,然后进行清除回收。缺点:效率不高,无法清除垃圾碎片。
  • 复制算法:按照容量划分二个大小相等的内存区域,当一块用完的时候将活着的对象复制到另一块上,然后再把已使用的内存空间一次清理掉。缺点:内存使用率不高,只有原来的一半。
  • 标记-整理算法:标记无用对象,让所有存活的对象都向一端移动,然后直接清除掉端边界以外的内存。
  • 分代算法:根据对象存活周期的不同将内存划分为几块,一般是新生代和老年代,新生代基本采用复制算法,老年代采用标记整理算法。

七、G1与CMS异同(这一个问题我被问到过,当时没怎么回答清楚,咱们需要理解两个作用的位置,以及使用的算法及对比的优劣之处)
1、CMS是以获取最短回收停顿时间为目标的收集器,基于并发“标记清理”实现,作用于老年代,并发效率高,就是会有大量空间碎片。
2、G1可以独立完成对内存的管理,使用了特别的分区,分了很多的region,还可以建立可预测的停顿时间模型,避免全堆扫描,G1使用了Remembered Set来管理相关的对象引用信息。
2. Java并发包常用工具类类用法和原理、会配合集合类一起考,还有volatile、CAS原理等等
Java问题整理总结
咱们可以参考这一篇文章,关于并发包工具类写的很详细
我讲一下volatile和CAS原理。
在这里先介绍一下并发编程的两个概念:
(1)原子性:(这里暂且用数据库的事务的原子性来解释,跟并发编程里面的原子性是同一个意思)
一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样
(2)可见性:
可见性是指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。
volatile:
在多核CPU的情况下,如果一个CPU进行了计算,然而其他CPU里面的缓存数据还是旧的,那么就会导致计算出错(脏数据)的情况,为了避免这种情况,保证多个CPU之间的高速缓存是一致的,OS里面会有一个缓存一致性协议,volatile就是通过OS的缓存一致性策略来保持共享变量在多个线程之间的可见性。
局限性:在并发情况下,还是可能会出现数据丢失的情况,不能保证并发情况下对共享变量的访问。
CAS:
含义:CAS是指compare and swap,意识是指一个旧的预期值A,主内存的值是B,要修改的值C,当且仅当A==B的时候,A的值才会被修改成C,而且这个操作是原子性的,是一个非阻塞性的乐观锁
原理:CAS底层是通过JNI去调用,是java通过调用C代码操作OS来获取的一个原子操作,通过看sun.misc.Unsafe类里面的方法,可以看到compareAndSwap()是一个native方法。具体就不说了,可以去看一下OS底层源码,里面涉及到了LOCK硬件指令。
局限性:会遇到ABA问题,自旋效率还有只能保证一个共享变量的原子操作。
3. MySQL也算是必问的东西了,索引存储结构、索引搜索原理、事务的隔离级别和原理。还有基本的MySQL处理数据库语句,查询连接之类的。我时常会提到学习了Redis,那么就会问一下Redis,5大数据结构,zset的原理,使用场景,Redis设计模式,多路复用等等。
4. 框架也是必备的知识点,最常见的AOP、DI原理,自己怎么实现?SpringBoot有什么原理,还会配合一些设计模式一起考,比如你最熟悉的设计模式是啥?有何作用?Spring MVC 里面用了什么设计模式?解决了什么问题?
应届生面试的要求一般都是有扎实的Java基础,熟悉io,多线程,集合等基础框架,具备系统调优、性能调优等技能,熟悉ssm框架阅读过源码优先。对疑难技术排除这些什么的工作经验问题了就是。总的来说刚开始还是要重视自己的笔试能力,要在学习回答问题的基础上熟悉对于Java技术的掌握,很多基础的知识点,记住了但是应用到题目中就会不知所措,我这里就放几道做过的题目来考考大家。

  1. int 的最大值:
  2. 哪些类是线程安全的:A、HashMap B、String C、ArrayList D、Integer
  3. 以下哪些是maven的生命周期:A、clean B、compile C、package D、website
  4. java的三大集合主要包括:A、set B、List C、Map D、Array
  5. java的线程状态不包括以下哪几种:A、新建 B、等待 C、运行 D、可运行
  6. 以下哪些JSON格式是正确的:A、{a:1} B、{“a”,{b:5}} C、{“a”:“asasa”} D、{“a”,[1,2,3]}
  7. Java的元数据包括:A、枚举 B、类 C、接口 D、注解。
    做出来的可能在评论区留言交流。今天就到这里啦!