导读
就目前大环境来看,跳槽成功的难度比往年高不少。一个明显的感觉:今年的面试,不管一面仍是二面,都很考验Java程序员的技术功底。前段时间的面试跳槽的黄金段,成功升职加薪,不成功饱受打击。固然也要注意,跳槽时时刻刻都在发生,可是我建议你们跳槽以前,先想清楚为何要跳槽。切不可跟风,看到同事一个个都走了,本身也盲目的开始面试起来(期间也没有准备充分),究竟是由于技术缘由(影响本身的发展,偏移本身规划的轨迹),仍是钱给少了,不受重视。只有考虑好了跳出去后才不会后悔。
对于面试我花费了一年时间进行收集整理,终于整理完成一份四万字的Java面试核心知识点PDF文档,还有诸多面试专题的详细剖析。包含面试必问知识点:Java集合,JVM,多线程,微服务,源码框架,分布式,设计模式,消息中间件,数据结构,算法等等。原预计花六个月零碎时间整理,没想到最后花了将近一年的时间才完成。因为文章篇幅限制,下面分享出来的将是以面试题或图片形式展示出来,但愿对各位同仁接下来的面试已经自身知识体系理解有必定的帮助。
-
近期想跳槽,要面试的Java程序员,查漏补缺,以便尽快弥补短板;
-
想了解“一线互联网公司”最新技术要求,对比找出自身的长处和弱点所在,评估本身在现有市场上的竞争力如何;
-
作了几年Java开发,但还没造成系统的Java知识体系,缺少清晰的提高方向和学习路径的程序员。
-
垃圾回收与算法
-
java四种引用类型
-
GC分代收集算法VS分区收集算法
-
GC垃圾收集器
部分JVM面试题
1.什么是Java虚拟机?为何Java被称做是“平台无关的编程语言”?
Java虚拟机是一个能够执行Java字节码的虚拟机进程。Java源文件被编译成能被Java虚拟机执行的字节码文件。 Java被设计成容许应用程序能够运行在任意的平台,而不须要程序员为每个平台单独重写或者是从新编译。Java虚拟机让这个变为可能,由于它知道底层硬件平台的指令长度和其余特性。
方法区和对是全部线程共享的内存区域;而java栈、本地方法栈和程序员计数器是运行是线程私有的内存区域。
-
Java堆(Heap),是Java虚拟机所管理的内存中最大的一块。Java堆是被全部线程共享的一块内存区域,在虚拟机启动时建立。此内存区域的惟一目的就是存放对象实例,几乎全部的对象实例都在这里分配内存。
-
方法区(Method Area),方法区(Method Area)与Java堆同样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
-
程序计数器(Program Counter Register),程序计数器(Program Counter Register)是一块较小的内存空间,它的做用能够看作是当前线程所执行的字节码的行号指示器。
-
JVM栈(JVM Stacks),与程序计数器同样,Java虚拟机栈(Java Virtual Machine Stacks)也是线程私有的,它的生命周期与线程相同。虚拟机栈描述的是Java方法执行的内存模型:每一个方法被执行的时候都会同时建立一个栈帧(Stack Frame)用于存储局部变量表、操做栈、动态连接、方法出口等信息。每个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
-
本地方法栈(Native Method Stacks),本地方法栈(Native Method Stacks)与虚拟机栈所发挥的做用是很是类似的,其区别不过是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的Native方法服务。
3.解释内存中的栈(stack)、堆(heap)和方法区(method area)的用法
一般咱们定义一个基本数据类型的变量,一个对象的引用,还有就是函数调用的现场保存都使用JVM中的栈空间;而经过new关键字和构造器建立的对象则放在堆空间,堆是垃圾收集器管理的主要区域,因为如今的垃圾收集器都采用分代收集算法,因此堆空间还能够细分为新生代和老生代,再具体一点能够分为Eden、Survivor(又可分为From Survivor和To Survivor)、Tenured;方法区和堆都是各个线程共享的内存区域,用于存储已经被JVM加载的类信息、常量、静态变量、JIT编译器编译后的代码等数据;程序中的字面量(literal)如直接书写的100、”hello”和常量都是放在常量池中,常量池是方法区的一部分,。栈空间操做起来最快可是栈很小,一般大量的对象都是放在堆空间,栈和堆的大小均可以经过JVM的启动参数来进行调整,栈空间用光了会引起StackOverflowError,而堆和常量池空间不足则会引起OutOfMemoryError。
上面的语句中变量str放在栈上,用new建立出来的字符串对象放在堆上,而”hello”这个字面量是放在方法区的。
补充1:较新版本的Java(从Java 6的某个更新开始)中,因为JIT编译器的发展和”逃逸分析”技术的逐渐成熟,栈上分配、标量替换等优化技术使得对象必定分配在堆上这件事情已经变得不那么绝对了。
补充2:运行时常量池至关于Class文件常量池具备动态性,Java语言并不要求常量必定只有编译期间才能产生,运行期间也能够将新的常量放入池中,String类的intern()方法就是这样的。 看看下面代码的执行结果是什么而且比较一下Java 7之前和之后的运行结果是否一致。
4.对象分配规则
java
-
对象优先分配在Eden区,若是Eden区没有足够的空间时,虚拟机执行一次Minor GC。
-
大对象直接进入老年代(大对象是指须要大量连续内存空间的对象)。这样作的目的是避免在Eden区和两个Survivor区之间发生大量的内存拷贝(新生代采用复制算法收集内存)。
-
长期存活的对象进入老年代。虚拟机为每一个对象定义了一个年龄计数器,若是对象通过了1次Minor GC那么对象会进入Survivor区,以后每通过一次Minor GC那么对象的年龄加1,知道达到阀值对象进入老年区。
-
动态判断对象的年龄。若是Survivor区中相同年龄的全部对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象能够直接进入老年代。
-
空间分配担保。每次进行Minor GC时,JVM会计算Survivor区移至老年区的对象的平均大小,若是这个值大于老年区的剩余值大小则进行一次Full GC,若是小于检查HandlePromotionFailure设置,若是true则只进行Monitor GC,若是false则进行Full GC。
类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,而后在堆区建立一个java.lang.Class对象,用来封装类在方法区内的数据结构。类的加载的最终产品是位于堆区中的Class对象,Class对象封装了类在方法区内的数据结构,而且向Java程序员提供了访问方法区内的数据结构的接口。
-
启动类加载器:Bootstrap ClassLoader,负责加载存放在JDK\jre\lib(JDK表明JDK的安装目录,下同)下,或被-Xbootclasspath参数指定的路径中的,而且能被虚拟机识别的类库
-
扩展类加载器:Extension ClassLoader,该加载器由sun.misc.Launcher$ExtClassLoader实现,它负责加载DK\jre\lib\ext目录中,或者由java.ext.dirs系统变量指定的路径中的全部类库(如javax.*开头的类),开发者能够直接使用扩展类加载器。
-
应用程序类加载器:Application ClassLoader,该类加载器由sun.misc.Launcher$AppClassLoader来实现,它负责加载用户类路径(ClassPath)所指定的类,开发者能够直接使用该类加载器
答:JVM中类的装载是由类加载器(ClassLoader)和它的子类来实现的,Java中的类加载器是一个重要的Java运行时系统组件,它负责在运行时查找和装入类文件中的类。 因为Java的跨平台性,通过编译的Java源程序并非一个可执行程序,而是一个或多个类文件。当Java程序须要使用某个类时,JVM会确保这个类已经被加载、链接(验证、准备和解析)和初始化。类的加载是指把类的.class文件中的数据读入到内存中,一般是建立一个字节数组读入.class文件,而后产生与所加载类对应的Class对象。加载完成后,Class对象还不完整,因此此时的类还不可用。当类被加载后就进入链接阶段,这一阶段包括验证、准备(为静态变量分配内存并设置默认的初始值)和解析(将符号引用替换为直接引用)三个步骤。最后JVM对类进行初始化,包括:1)若是类存在直接的父类而且这个类尚未被初始化,那么就先初始化父类;2)若是类中存在初始化语句,就依次执行这些初始化语句。 类的加载是由类加载器完成的,类加载器包括:根加载器(BootStrap)、扩展加载器(Extension)、系统加载器(System)和用户自定义类加载器(java.lang.ClassLoader的子类)。从Java 2(JDK 1.2)开始,类加载过程采起了父亲委托机制(PDM)。PDM更好的保证了Java平台的安全性,在该机制中,JVM自带的Bootstrap是根加载器,其余的加载器都有且仅有一个父类加载器。类的加载首先请求父类加载器加载,父类加载器无能为力时才由其子类加载器自行加载。JVM不会向Java程序提供对Bootstrap的引用。下面是关于几个类加载器的说明:
-
Bootstrap:通常用本地代码实现,负责加载JVM基础核心类库(rt.jar);
-
Extension:从java.ext.dirs系统属性所指定的目录中加载类库,它的父加载器是Bootstrap;
-
System:又叫应用类加载器,其父类是Extension。它是应用最普遍的类加载器。它从环境变量classpath或者系统属性java.class.path所指定的目录中记载类,是用户自定义加载器的默认父加载器。
JVM中类的装载是由类加载器(ClassLoader)和它的子类来实现的,Java中的类加载器是一个重要的Java运行时系统组件,它负责在运行时查找和装入类文件中的类。
因为Java的跨平台性,通过编译的Java源程序并非一个可执行程序,而是一个或多个类文件。当Java程序须要使用某个类时,JVM会确保这个类已经被加载、链接(验证、准备和解析)和初始化。类的加载是指把类的.class文件中的数据读入到内存中,一般是建立一个字节数组读入.class文件,而后产生与所加载类对应的Class对象。加载完成后,Class对象还不完整,因此此时的类还不可用。当类被加载后就进入链接阶段,这一阶段包括验证、准备(为静态变量分配内存并设置默认的初始值)和解析(将符号引用替换为直接引用)三个步骤。最后JVM对类进行初始化,包括:
类的加载是由类加载器完成的,类加载器包括:根加载器(BootStrap)、扩展加载器(Extension)、系统加载器(System)和用户自定义类加载器(java.lang.ClassLoader的子类)。
从Java 2(JDK 1.2)开始,类加载过程采起了父亲委托机制(PDM)。PDM更好的保证了Java平台的安全性,在该机制中,JVM自带的Bootstrap是根加载器,其余的加载器都有且仅有一个父类加载器。类的加载首先请求父类加载器加载,父类加载器无能为力时才由其子类加载器自行加载。JVM不会向Java程序提供对Bootstrap的引用。下面是关于几个类加载器的说明:
-
Bootstrap:通常用本地代码实现,负责加载JVM基础核心类库(rt.jar);
-
Extension:从java.ext.dirs系统属性所指定的目录中加载类库,它的父加载器是Bootstrap;
-
System:又叫应用类加载器,其父类是Extension。它是应用最普遍的类加载器。它从环境变量classpath或者系统属性java.class.path所指定的目录中记载类,是用户自定义加载器的默认父加载器。
19.新生代垃圾回收器和老生代垃圾回收器都有哪些?有什么区别?
更多资料展现
**因为篇幅限制小编,pdf文档的详解资料太全面,细节内容实在太多啦,因此只把部分知识点截图出来粗略的介绍,每一个小节点里面都有更细化的内容!
资料获取方式:须要这份PDF文档的朋友点赞,关注个人公众号【java小瓜哥的分享平台】就能免费获取领取方式了!