阿里P7讲解java面试填坑解惑篇
哥们儿告诉我应聘者和往常一样甚至变少,因此大家不用太担心,只要认真准备技术知识和我之前讲到的技术面试话语基本都能找到一份如意的工作。
话不多说,言归正传我们来解答上期大家的疑问吧。
NO1.请简单描述JDK和JRE的区别?
回答JDK和JRE的区别这道题,首先要回答两个名次的概念,JDK就是Java Developement Kit的缩写,java最核心的东西,包括了java的运行环境(JRE),一些基本类库方便开发人员开发程序和源码压缩等。主要由bin(可执行命令如javac,java等)、include(和java虚拟机交互的头文件)、lib(java类库)、 jre(运行环境)组成。
而JRE(Java Runtime Environment)是java的运行环境,包含java虚拟机和一些基本运行类库,但不包括调试和开发工具,一个项目被编译为.class后缀后即可在JRE上运行。
顺便补一下上面提到的JVM(Java Virtual Machine)知识,JVM是 java运行时所需要的环境,JVM是一种用于计算设备的规范,它是一个虚构出来的微小计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。针对java用户,也就是拥有可运行的.class文件包(jar或者war)的用户。
里面主要包含了jvm和java运行时基本类库(rt.jar)。rt.jar可以理解为java源码编译后的jar包。Java虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行,比如windows或者linux。这就是Java所宣称的“一次编译,到处运行”的原因。
NO2.告诉我JVM的类加载过程?对不起各位这里直接提升了面试的难度,但是工作三年以上的中级程序员还是需要了解的,看图说话还差哪些过程么。
第二题考察大家对JVM加载class的理解程度,题目的图中缺少的步骤为应用和卸载两步,因为当JVM完成前面三步以后就等系统调用,当实例完成线程任务后即被JVM进行GC,当Class不被引用后就会被卸载。
NO3.工作快三年了,了解多JVM的双亲委派模式么,为什么需要由父类加载类再传递给最下面的类加载器?
java中可以加载类的加载器由高到低顺序为BootstrapClassLoader,ExtensionClassLoader,AppClassLoader三类,JVM加载类时都是由AppClassLoader请求他的父类ExtensionClassLoader进行加载,如果父类可以加载类到虚拟机则子类不能再加载类,依次类推,只有那些一二级类加载器都没发现的类才被AppClassLoader加载,这类class可以理解为自定义类。这样设置的初衷主要是出于安全考虑,免得被不怀好意的人破篡改API类库。
NO4.对了如何如何控制多个子线程任务执行完成,再执行主线程程序?除了thread.join(2000),还有其他方法么?
在主线程中启动子线程,为了保证子线程统一执行完成再执行主线程代码除了上面提到的join(),join(2000)外,其实还可以使用countDownLatch方法,主要实现原理是通过在主程序中设置子线程数量,同时在子线程中调用countDownLatch.countDown()方法计数达到统计线程的目的,顺便提到一下CyclicBarrier目的是让子线程同时完成的,感兴趣的同学可以多去了解下。
NO5. 下面的代码执行以后S1,S2分别等于多少?还是说会出现什么问题?
此题主要考察越界和转化的问题,S1的值是-128,S2的值是2。第一行代码因为byte最大值是127在计算机中表示为01111111加1后变为10000000此时是补码,计算机只存储补码,此时计算机都是通过补码来表示数值的11111111的补码是符号位不变其他位取反为10000000(源码)就是-128,S2的时候其实是Integer类型强制转换的结果。
NO6.年轻人,请回答一下servlet的生命周期,这个对于了解配置加载和预加载参数有重要意义?
主要考察对容器生命周期的理解,无论后面出现怎样的框架,底层始终都没有变化,答案基本回答到点上了,说一句目前的大多框架都是默认单例类实例的,因此使用完成后不会被destroy掉。
NO7.想必你知道一些关于threadLocal的知识,我不问你怎么使用,也不问你使用场景。我想说的是线程池提供给用户的线程会存在数据混淆么?(这个可能有点高端,有些高级开发都不知道,呵呵)
关于threadLocal知识,目前来说使用的不是很多,大家可以了解他的使用场景是为了隔离数据,就是说希望线程各自访问各自的数据互不干涉。题目中的坑其实就是线程池公用出现的问题,当上一个线程不是新创建的而是来自线程池时存在threadLocal中止没被清空的情况,造成数据篡写。正确的做法就是每次使用完成后都立马置为null,这样伴随着线程销毁,变量也被销毁。
NO8.知道序列化吧,什么情况下需要序列化?RPC服务中的参数为啥都需要序列化呢?参数中的日期类型到底用sql.Date还是util.Date?
这道题其实是考察序列化的场景的,序列化的目的依赖为了进行网络传输,确保传过去的字节流还能被反编译找到对应的类,二来为了方便本地硬盘存储。RPC(Remote Protocal Call)服务为异步服务都是通过网络传输数据,当然需要序列化数据。Java.sql.Date类继承java.util.Date类,但是并未实现序列化因此作为参数不能在RPC服务中传输。