1.1 JVM内存结构
(1)程序计数器
线程私有;
没有内存溢出;
(2)虚拟机栈
线程私有;
后入先出数据结构;
只有一个栈帧活跃状态,处于栈顶;
(3)本地方法区
与虚拟机栈相似;
虚拟机栈为java方法服务,本地方法栈是为Native方法(包含其它语言)服务的。
(4)方法区
储存类结构信息(常量、静态变量、构造函数等,类信息是类加载器从类加载时获取);
存在垃圾收集
线程共享
(5)堆
存储实例或者对象的地方,GC主要区域;
线程共享
实例:
stu是对Student对象的引用,放入栈中,指向堆中对象的内存地址
new 出来的Student对象放入堆中,并持有方法区中Student类型信息的引用。
Student stu=new Student(“zs”);
执行add()方法时,根据stu定位到堆中的对象实例,再根据堆中持有位于方法区的Student类型信息,获得add()字节码,执行此方法执行,打印出结果。
stu.add();
(1)创建对象,JVM从方法区寻找对象类型信息,没有,使用类加载器classloader加载到内存中方法区;
(2)JVM在堆分配实例内存空间,实例持有指向方法区类型信息引用(方法区的内存地址);
(3)JVM创建线程执行,同时创建虚拟机栈,虚拟机栈跟踪线程运行中的方法一系列过程,每执行一个方法往栈中压入一个栈帧,栈帧存储方法参数,局部变量和运算过程的临时数据。例子中,stu是Student的引用,存于栈中,指向堆中Student实例的内存地址。
(4)JVM根据stu引用堆中对象内存地址定位实例,堆中持有方法区类型信息引用,获取方法字节码信息,执行方法指令。
总结:
(1)方法区、堆线程共享。虚拟机栈、本地方法区和程序计数器线程私有。
(2)栈中存放东西:
a、基础数据类型、自定义对象引用(不是对象);
b、每个栈数据都是线程私有,不能访问;
c、方法形式参数,方法调用完从栈中回收;
d、引用对象地址,引用完,栈空间立即回收,堆空间等待GC
(3)堆中存放东西:
a、存储的全部是对象,每个对象包含一个与之对应的class信息
b、JVM一个堆区,线程共享,不存放基本类型和对象引用,只存储对象本身
(4)存放方法区:
a、存放线程执行的字节码指令
b、和堆都是线程共享,包含所有class和static变量
c、常量池位于方法区中。