JVM的内存结构

JAVA源代码文件通过编译后变成虚拟机可以识别的字节码,JAVA程序在执行时,会通过类加载器把字节码加载到虚拟机的内存中(虚拟机的内存是一个逻辑概念,相当于是对主内存的一个抽象,实际上真实的数据还是存放在主存中),详见下图。

Java 虚拟机在执行 Java 程序的过程中会把它管理的内存划分为若干个不同的数据区域。每个区域都有各自的作用。分析 JVM 内存结构,主要就是分析JVM 运行时数据存储区域。JVM 的运行时数据区主要包括:堆、栈、方法区、程序计数器等。而 JVM 的优化问题主要在线程共享的数据区中:堆、方法区。

1 方法区

又称非堆(non-heap),方法区用于存储已被虚拟机加载的类信息,常量、静态变量,即时编译后的代码等数据。方法区中最著名的就是CLASS对象,CLASS对象中存放了类的元数据信息,包括:类的名称、类的加载器、类的方法、类的注解等。当我们new一个新对象或者引用静态成员变量时,Java虚拟机(JVM)中的类加载器子系统会将对应Class对象加载到JVM中,然后JVM再根据这个类型信息相关的Class对象创建我们需要实例对象或者提供静态变量的引用值。注意,我们定义的一个类,无论创建多少个实例对象,在JVM中都只有一个Class对象与其对应,即:在内存中每个类有且只有一个相对应的Class对象,如图:

实际上所有的类都是在对其第一次使用时动态加载到JVM中的,当程序创建第一个对类的静态成员引用时,就会加载这个被使用的类(实际上加载的就是这个类的字节码文件)。注:使用new创建类的新实例对象也会被当作对类的静态成员的引用(构造函数也是类的静态方法)由此看来Java程序在它们开始运行之前并非被完全加载到内存的,其各个部分是按需加载,所以在使用该类时,类加载器首先会检查这个类的Class对象是否已被加载(类的实例对象创建时依据Class对象中类型信息完成的),如果还没有加载,默认的类加载器就会先根据类名查找.class文件(编译后Class对象被保存在同名的.class文件中),在这个类的字节码文件被加载时,它们必须接受相关验证,以确保其没有被破坏并且不包含不良Java代码(这是java的安全机制检测),完全没有问题后就会被动态加载到内存中,此时相当于Class对象也就被载入内存了(毕竟.class字节码文件保存的就是Class对象),同时也就可以根据这个类的Class对象来创建这个类的所有实例对象。

2 堆

所有创建出来的实例对象还有数组都是存放在堆内存中,堆是Java虚拟机所管理的内存中最大的一块存储区域,堆内存被所有线程共享。垃圾收集器就是根据GC算法,收集堆上对象所占用的内存空间,堆上又分为了新生代和老年代,针对不同的分代又会有对象的垃圾回收器和相应的回收算法(GC章节中会详细介绍)。

3 栈

展开阅读全文

本文系作者在时代Java发表,未经许可,不得转载。

如有侵权,请联系nowjava@qq.com删除。

编辑于

关注时代Java

关注时代Java