java面试(进阶四篇)解答

题目来自于网络,答案是笔者整理的。仅供参考,欢迎指正

来源: https://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&mid=2247485779&idx=1&sn=3b06b9923df7f40f887ead8b8a53e50e&chksm=e9c5f0e2deb279f47fbfc3a12a70896bf95fa8c631939b87c85aea904785d10cb12667fa8724&scene=21&key=cf3fe9b79f0039bfe34c8540f1d4d5de82bd92d9536ebde316816880408f94640a5655f53e9e7cc11797ca27f4eee4a8a291910ef31ddaa1f6dfad4c648500c76477eff18997fabf8c722aef8b3aca4b&ascene=7&uin=MjM2OTQ3MDkzOQ%3D%3D&devicetype=Windows+7&version=6206021b&lang=zh_CN&pass_ticket=h97v%2FevjbeMS22Cec6mLcTFMVU17Iq0u%2FWtXpCY668m3AU7lLNOkKa9JdWj%2B8omE&winzoom=1

 

一、Java基础

  • 为什么JVM调优经常会将-Xms和-Xmx参数设置成一样;

  • Java线程池的核心属性以及处理流程;

  • Java内存模型,方法区存什么;

  • CMS垃圾回收过程;

  • Full GC次数太多了,如何优化;

  • 直接内存如何管理的;

  • Java线程池的几个参数的意义和实现机制;

  • Java线程池使用无界任务队列和有界任务队列的优劣对比;

  • CountDownLatch和CyclicBarrier的区别;

  • Java中有哪些同步方案(重量级锁、显式锁、并发容器、并发同步器、CAS、volatile、AQS等)

  • 如果你的项目出现了内存泄露,怎么监控这个问题呢;

  • 标记清除和标记整理的区别和优缺点,为何标记整理会发生stop the world;

  • 线程池,如何根据CPU的核数来设计线程大小,如果是计算机密集型的呢,如果是IO密集型的呢?

  • 让你设计一个cache如何设计;

  • String中hashcode是怎么实现的;

  • JDK中哪些实现了单例模式?

  • 多个线程同时读写,读线程的数量远远⼤于写线程,你认为应该如何解决并发的问题?你会选择加什么样的锁?

  • 线程池内的线程如果全部忙,提交⼀个新的任务,会发⽣什么?队列全部塞满了之后,还是忙,再提交会发⽣什么?

  • synchronized关键字锁住的是什么东西?在字节码中是怎么表示的?在内存中的对象上表现为什么?

  • wait/notify/notifyAll⽅法需不需要被包含在synchronized块中?这是为什么?

  • ExecutorService你一般是怎么⽤的?是每个Service放一个还是个项目放一个?有什么好处?

二、数据库

  • InnoDB的插入缓冲和两次写的概率和意义;

  • 如果建了⼀个单列索引,查询的时候查出2列,会⽤到这个单列索引吗?(会用到)

  • 如果建了⼀个包含多个列的索引,查询的时候只⽤了第⼀列,能不能⽤上这个索引?查三列呢?

  • 接上题,如果where条件后⾯带有⼀个 i + 5 < 100 会使⽤到这个索引吗?

  • like %aaa%会使⽤索引吗? like aaa%呢?

  • drop、truncate、delete的区别?

  • 平时你们是怎么监控数据库的? 慢SQL是怎么排查的?(慢查询日志)

  • 你们数据库是否⽀持emoji表情,如果不⽀持,如何操作?选择什么编码方式?如果支持一个表情占几个字节?(utf8mb4);

  • 如果查询很慢,你会想到的第⼀个⽅式是什么?(数据库索引)

三、Linux基础

  • Linux下可以在/proc目录下可以查看CPU的核心数等;cat /proc/下边会有很多系统内核信息可供显示; 

  • 说一下栈的内存是怎么分配的;

  • Linux各个目录有了解过吗?/etc、/bin、/dev、/lib、/sbin这些常见的目录主要作用是什么?

  • 说一下栈帧的内存是怎么分配的;

  • Linux下排查某个死循环的线程;

  • 动态链接和静态链接的区别;

  • 进程的内存分布;

  • 如何查找一个进程打开所有的文件;

  • 说一下常使用的协议及其对应的端口;

  • 为什么会有内核态,保护模式你知道吗?

  • 文件是怎么在磁盘上存储的?

  • 有了进程为何还要线程呢,不同进程和线程他们之间有什么不同。(进程是资源管理的最小单位,线程是程序执行的最小单位。在操作系统设计上,从进程演化出线程,最主要的目的就是更好的支持SMP以及减小(进程/线程)上下文切换开销。)

  • InnoDB聚集索引B+树叶子节点和磁盘什么顺序相同;

  • 文件系统,进程管理和调度,内存管理机制、虚地址保护模式;

四、网络基础

  • HTTP1.0和HTTP1.1的区别;

  • DHCP如何实现分配IP的; 发现阶段(DHCP客户端在网络中广播发送DHCP DISCOVER请求报文,发现DHCP服务器,请求IP地址租约)、提供阶段(DHCP服务器通过DHCP OFFER报文向DHCP客户端提供IP地址预分配)、选择阶段(DHCP客户端通过DHCP REQUEST报文确认选择第一个DHCP服务器为它提供IP地址自动分配服务)和确认阶段(被选择的DHCP服务器通过DHCP ACK报文把在DHCP OFFER报文中准备的IP地址租约给对应DHCP客户端)。

  • OSI七层模型,每层都说下自己的理解和知道的,说的越多越好;

五、框架相关

  • Servlet如何保证单例模式,可不可以编程多例的哪?

  • Dubbo请求流程以及原理;

  • Spring框架如何实现事务的;

  • 如果一个接⼝有2个不同的实现, 那么怎么来Autowire一个指定的实现?(可以使用Qualifier注解限定要注入的Bean,也可以使用Qualifier和Autowire注解指定要获取的bean,也可以使用Resource注解的name属性指定要获取的Bean)

  • Spring框架中需要引用哪些jar包,以及这些jar包的用途;

  • Spring Boot没有放到web容器⾥为什么能跑HTTP服务?

  • Spring中循环注入是什么意思,可不可以解决,如何解决;

  • Spring的声明式事务 @Transaction注解⼀般写在什么位置? 抛出了异常会⾃动回滚吗?有没有办法控制不触发回滚?

  • MyBatis怎么防止SQL注入;

  • Tomcat本身的参数你⼀般会怎么调整?

  • 了解哪几种序列化协议?如何选择合适的序列化协议;

  • Redis渐进式rehash过程?

  • 比如我有个电商平台,做每日订单的异常检测,服务端代码应该写;

 

参考答案

一、Java基础

 

1.为什么JVM调优经常会将-Xms和-Xmx参数设置成一样

    避免java堆自动扩展。

    java垃圾回收机制清理完堆区之后不需要重新计算堆区的大小而浪费资源

 

2.Java线程池的核心属性以及处理流程

    流程:

    * 当线程池线程数

    * 当线程池线程数=corePoolSize时,再有任务提交,会将任务放置在workQueue里,一个阻塞的队列

    * 当队列也放满后,并且线程池数

    * 当线程池数=maxPoolSize时,此时若再有新任务提交,则执行拒绝策略

 

3.Java内存模型,方法区存什么

java面试(进阶四篇)解答_第1张图片

    方法区主要存放静态变量、常量、类元数据信息

 

4.CMS垃圾回收过程  

1、初始标记(CMS Initial mark)    Stop the World   仅仅标记一下GC Roots能直接关联到的对象,速度快
2、并发标记(CMS concurrent mark) 进行GC Roots Tracing(根搜索算法,判断对象是否仍在使用中),时间长,不发生用户进程停顿
3、重新标记(CMS remark)          Stop the World   修正并发标记期间因用户程序继续运行导致标记变动的那一部分对象的标记记录,停顿时间较长,但远比并发标记时间短
4、并发清除(CMS concurrent sweep) 清除的同时用户进程会导致新的垃圾,时间长,不发生用户进程停顿

5.Full GC次数太多了,如何优化

    MinorGC:发生在新生代的GC,当新生代没有足够空间来分配给新对象时就会发生

    FullGC:发生在老年代的GC,当老年代没有足够空间来分配给新对象就会发生;老年代需要为新生代预留一部分担保空间,所以如果动态担保空间不足也会发生一次FullGC

 

    触发JVM进行FullGC的几种情况及应对策略

    1)System.gc()方法的调用

        该方法会建议JVM进行FullGC,会增加FullGC的频率,不建议使用该方法

        应对策略:通过设置XX:+ DisableExplicitGC来禁止RMI调用System.gc

 

    2)老年代空间不足

        老年代只有在新生代对象转入及创建大对象、大数组才会出现不足的情况

        应对策略:调优时应该尽量让对象在MinorGC阶段被回收;避免创建大对象

 

    3)方法区空间不足

        当系统中要加载的类、反射的类和调用的方法较多时,方法区有可能被占满,在未配置采用CMS GC的情况下也会发生FullGC

        应对策略:增大方法区空间大小;专为CMS GC

 

    看不明白的以下两个:

4、CMS GC时出现promotion failed和concurrent mode failure

对于采用CMS进行老年代GC的程序而言,尤其要注意GC日志中是否有promotion failed和concurrent mode failure两种状况,当这两种状况出现时可能

会触发Full GC。
promotion failed是在进行Minor GC时,survivor space放不下、对象只能放入老年代,而此时老年代也放不下造成的;concurrent mode failure是在

执行CMS GC的过程中同时有对象要放入老年代,而此时老年代空间不足造成的(有时候“空间不足”是CMS GC时当前的浮动垃圾过多导致暂时性的空间不足触发Full GC)。
对措施为:增大survivor space、老年代空间或调低触发并发GC的比率,但在JDK 5.0+、6.0+的版本中有可能会由于JDK的bug29导致CMS在remark完毕

后很久才触发sweeping动作。对于这种状况,可通过设置-XX: CMSMaxAbortablePrecleanTime=5(单位为ms)来避免。


5、统计得到的Minor GC晋升到旧生代的平均大小大于老年代的剩余空间

这是一个较为复杂的触发情况,Hotspot为了避免由于新生代对象晋升到旧生代导致旧生代空间不足的现象,在进行Minor GC时,做了一个判断,如果之

前统计所得到的Minor GC晋升到旧生代的平均大小大于旧生代的剩余空间,那么就直接触发Full GC。
例如程序第一次触发Minor GC后,有6MB的对象晋升到旧生代,那么当下一次Minor GC发生时,首先检查旧生代的剩余空间是否大于6MB,如果小于6MB,

则执行Full GC。
当新生代采用PS GC时,方式稍有不同,PS GC是在Minor GC后也会检查,例如上面的例子中第一次Minor GC后,PS GC会检查此时旧生代的剩余空间是否

大于6MB,如小于,则触发对旧生代的回收。
除了以上4种状况外,对于使用RMI来进行RPC或管理的Sun JDK应用而言,默认情况下会一小时执行一次Full GC。可通过在启动时通过- java -

Dsun.rmi.dgc.client.gcInterval=3600000来设置Full GC执行的间隔时间或通过-XX:+ DisableExplicitGC来禁止RMI调用System.gc。
--------------------- 
作者:end 
来源:CSDN 
原文:https://blog.csdn.net/endlu/article/details/51144918 
版权声明:本文为博主原创文章,转载请附上博文链接!

6.直接内存如何管理的

    NIO的Buffer提供了一个可以不经过JVM内存直接访问系统物理内存的类-DirectBuffer

    DirectBuffer继承自ByteBuffer,但和普通的ByteBuffer不同。

        普通的ByteBuffer分配在堆内存上,其最大大小受限于最大堆内存的限制;

        而DirectBuffer直接分配在物理内存上,并不占用堆内存,其可申请的最大内存受限于操作系统

 

    直接内存的读写操作比普通Buffer快,但它的创建销毁比普通Buffer慢;因此直接内存适合于使用大内存空间并且频繁访问的场合,不适合频繁释放申请内存的场合

 

    注意:DirectBuffer并没有真正向OS申请分配内存,其最终还是通过调用Unsafe的allocateMemory()来进行内存分配。不过JVM对Direct Memory可申请的大小也有限制,可用-XX:MaxDirectMemorySize=1M设置,这部分内存不受JVM垃圾回收管理。

 

    

7.Java线程池的几个参数的意义和实现机制

    参考2

 

8.Java线程池使用无界任务队列和有界任务队列的优劣对比

    无界队列除非系统资源耗尽,否则不会出现拒绝任务入队的情况。

    若任务创建和处理的差异很大,那么无界队列会快速增长,直到耗尽系统资源    

 

9.CountDownLatch和CyclicBarrier的区别

    * CountDownLatch:闭锁的功能类似于一扇门,在闭锁达到结束状态之前,门是一直关闭的,没有任何线程能够通过。当达到结束状态时,

这扇门会打开并允许所有的线程通过。闭锁可以用来确保某些活动直到其他活动结束后才继续执行

    * CyclicBarrier:栅栏类似于闭锁,它能阻止一组线程直到某个事件发生。

    不同点在于:闭锁做减法计数,栅栏做加法计数;闭锁是一次性的,栅栏可重复使用;闭锁用于等待事件,栅栏用于等待其他线程
 

 

10.Java中有哪些同步方案

    Synchronized、ReentrantLock、同步容器、CAS、volatile等

 

11.如果你的项目出现了内存泄露,怎么监控这个问题呢

    // TODO

 

12.标记清除和标记整理的区别和优缺点,为何标记整理会发生stop the world

    标记清除:会将需要回收的内存标记下来,然后进行清除。会造成内存碎片,大量的内存碎片会导致另一次GC

    标记整理:标记过程与标记清除类似,整理过程则是将所有存活的对象向一侧移动,然后直接清除边界以外的内存

 

13.线程池,如何根据CPU的核数来设计线程大小,如果是计算机密集型的呢,如果是IO密集型的呢

    计算密集型:在N CPU的处理器上工作,N+1个线程最优

    IO密集型:线程数=((线程等待时间+线程CPU时间)/线程CPU时间)*CPU数目

 

14.让你设计一个cache如何设计

    主要是想知道如何设计cache的算法

    cache的算法设计常见的有:FIFO(先进先出)、LRU(least recently used最近最少使用)、LFU(least Frequently used最不经常使用)

    具体可参考:https://www.cnblogs.com/davidwang456/p/4001342.html 

 

15.String中hashcode是怎么实现的

    hashCode的计算应用在集合中的时候,我们通过hashCode来比较两个对象是否相等,如果hashCode不相等则两个对象一定不等。如果hashCode相等的话再调用对象的equals方法来比较。

    由于hashCode的比较比equals的比较快的多,所以我们在设计hashCode的时候要尽可能的让hashCode不重复。

 

    String.hashCode()源码如下:

    public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }

    更多可参考:https://blog.csdn.net/myspacedemen/article/details/53353480  

 

16.JDK中哪些实现了单例模式

    java.lang.Runtime,可以控制JVM的状态和行为

    java.lang.reflect.Proxy感觉不像单例模式

 

17.多个线程同时读写,读线程的数量远远⼤于写线程,你认为应该如何解决并发的问题?你会选择加什么样的锁

    ReentrantReadWriteLock读写锁

 

18.线程池内的线程如果全部忙,提交⼀个新的任务,会发⽣什么?队列全部塞满了之后,还是忙,再提交会发⽣什么?

   线程池内的线程如果全部忙,提交⼀个新的任务,会将任务添加到队列中

   队列全部塞满了之后,还是忙,再提交会创建新的线程执行任务,直到线程数=maxPoolSize

   之后在提交会执行拒绝策略  

 

19.synchronized关键字锁住的是什么东西?在字节码中是怎么表示的?在内存中的对象上表现为什么?

    // TODO    

 

20.wait/notify/notifyAll⽅法需不需要被包含在synchronized块中?这是为什么?

    需要,只有持有锁的线程才能够调用对象的wait、notify等这些方法

 

21.ExecutorService你一般是怎么⽤的?是每个Service放一个还是个项目放一个?有什么好处?

    最好不要按项目来放,按不同的任务类型来放置最好。

    有的任务执行的时间长,有的任务执行的时间短,如果都使用一个线程池的话,执行任务时间长的容易阻塞住线程,导致其他执行时间短的任务无法获取到线程

 

 

未完待续...

 

 

 

 

 

 

你可能感兴趣的:(CoreJava)