垃圾收集算法

Java内存运行时的各个部分,其中程序计数器、虚拟机栈、本地方法栈3个区域随线程而生,随线程而灭;栈中的栈帧随着方法的进入和退出而有条不絮地执行着出栈和入栈操作。每一个栈帧中分配多少内存基本上是在类结构确定下来时就已知的(尽管JIT编译器会进行一些优化,但大体可认为是编译期可预知的),因此这个几个区域内存的分配和回收都具备确定性。

Java堆方法区不一样,一个接口的多个实现类需要的内存可能不一样,一个方法的多个分支需要的内存也可能不一样,我们只有在程序处于运行期间才能知道会创建哪些对象,这部分内存的分配和回收都是动态的,因此垃圾收集器所关注的主要就是堆内存以及方法区。

运行时内存异常

在java虚拟机规范的描述中,除了程序计数器外,虚拟机内存的其他几个运行时区域都有发生OutOfMemoryError异常的可能

运行时数据区

Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域都有各自的用途,以及各自的创建和销毁时间,有的区域随虚拟机进程的启动而存在,有些区域则依赖用户线程的启动和结束而建立和销毁

编译 & 优化

Java的编译过程可以分为两个阶段,首先是将.java文件编译为.class文件的过程,称为前端编译,比如javac;然后在运行期,可能即时编译器(JIT)又会将字节码转变为本地机器码,比如HotSopt的C1、C2编译器,或者Graal编译器。

对于优化处理,Java虚拟机团队选择将性能优化的措施全部集中在运行期的即时编译器中,以便让那些不是由 javac 产生的 Class 文件也能享受到性能优化的好处,至于 javac 中则做了一些针对Java语言编码过程的优化,用来降低开发者的编码复杂度、提高编码效率。可以这样认为,即时编译器在运行期的优化过程,支撑了程序执行效率的不断提升,而javac在编译期的优化过程,则支撑了开发者的编码效率和语言使用者的体验。

动态类型语言支持

Java虚拟机的字节码指令集自Sun公司推出第一款Java虚拟机至今,二十余年间只新增过一条指令,它就是随着JDK 7一起发布的 invokedynamic 指令。这条新增指令是JDK 7的项目目标:实现动态类型语言支持而进行的改进之一,也是为JDK 8中可以顺利实现 Lambda 表达式而做的技术储备。

方法调用 重载 & 重写

Java虚拟机以方法作为最基本的执行单元,而栈帧则是用于支持虚拟机进行方法调用和方法执行背后的数据结构,它也是虚拟机运行时数据区中的虚拟机栈的栈元素。