vlambda博客
学习文章列表

JAVA应用程序开发之JVM基础

JVM 就是 java 虚拟机,包括一套字节码指令集,一组寄存器,一个栈,一个垃圾回收堆和一个存储方法域。Java 就是通过 JVM 来屏蔽系统差异,达到一次编译,处处运行能力的。

一般 Java 开发人员,是不需要了解 JVM 的。对 JVM 的参数进行调整, 比如最大堆尺寸、新生代切换到年老代的阀值, eden 和 survior 的比例等,这些决定了垃圾回收 young gc 和 full gc 的频率,对应用的性能会有影响的。

关于 JVM 相关的内容很多 , 本文仅作抛砖引玉 , 其他内容请大家自行学习 ( 推荐书籍《深入理解 java 虚拟机》 ) 。


类加载器( ClassLoader )(用来装载 .class 文件)

执行引擎(执行字节码,或者执行本地方法)

运行时数据区(方法区、堆、 java 栈、 PC 寄存器、本地方法栈)

PC 寄存器:

用于存储每个线程下一步将执行的 JVM 指令,如该方法为 native 的,则 PC 寄存器中不存储任何信息。

JVM 栈:

堆:

JVM 用来存储对象实例以及数组值的区域,可以认为 Java 中所有通过 new 创建的对象的内存都在此分配, Heap 中的对象的内存需要等待 GC 进行回收。

堆是 JVM 中所有线程共享的,因此在其上进行对象内存的分配均需要进行加锁,这也导致了 new 对象的开销是比较大的。

Sun Hotspot JVM 为了提升对象内存分配的效率,对于所创建的线程都会分配一块独立的空间 TLAB ( Thread Local Allocation Buffer ),其大小由 JVM 根据运行的情况计算而得,在 TLAB 上分配对象时不需要加锁,因此 JVM 在给线程的对象分配内存时会尽量的在 TLAB 上分配,在这种情况下 JVM 中分配对象内存的性能和 C 基本是一样高效的,但如果对象过大的话则仍然是直接使用堆空间分配

TLAB 仅作用于新生代的 Eden Space ,因此在编写 Java 程序时,通常多个小的对象比大的对象分配起来更加高效。

所有新创建的 Object 都将会存储在新生代 Yong Generation 中。如果 Young Generation 的数据在一次或多次 GC 后存活下来,那么将被转移到 OldGeneration 。新的 Object 总是创建在 Eden Space 。

方法区域( Method Area )

在 Sun JDK 中这块区域对应的为 PermanetGeneration ,又称为持久代。

方法区域存放了所加载的类的信息(名称、修饰符等)、类中的静态变量、类中定义为 final 类型的常量、类中的 Field 信息、类中的方法信息,当开发人员在程序中通过 Class 对象中的 getName 、 isInterface 等方法来获取信息时,这些数据都来源于方法区域,同时方法区域也是全局共享的,在一定的条件下它也会被 GC ,当方法区域需要使用的内存超过其允许的大小时,会抛出 OutOfMemory 的错误信息。

运行时常量池( Runtime Constant Pool ):

存放的为类中的固定的常量信息、方法和 Field 的引用信息等,其空间从方法区域中分配。

本地方法堆栈( Native Method Stacks ):

JVM 采用本地方法堆栈来支持 native 方法的执行,此区域用于存储每个 native 方法调用的状态。

使用 this.getClass.getClassLoader() 获取类加载器,类进入 JVM 之前会经过 ClassLoader ,因此可以使用其进行安全性校验;加密;对自己代码进行归档整理;自展开程序 ( 无需安装 , 直接在内存中自行展开 ) ;动态生成类。

部分文字与图片来源于网络,如有版权请联系删除!