Java虚拟机在Java程序执行时会将它管理的内存区域划分成若干个不同的数据区域。每个区域有不同的作用和生命周期,有的随着虚拟机进场的启动而创建,有的区域依赖用户线程的启动和结束来创建和销毁。
根据《Java虚拟机规范》的规定,Java虚拟机管理的内存包括以下几个。
线程私有。程序计数器是一块很小的内存空间,用来当作当前线程执行的字节码的行号指示器,CPU线程切换的时候继续通过它来确认线程执行到哪里了。
此区域是唯一一个在 Java虚拟机规范中没有规定任何OutOfMemoryError的区域
线程私有。生命周期与线程相同。每个方法在执行时都会创建一个虚拟机栈帧,用于存储局部变量表、操作数栈、动态链接、方法出入口等信息。
虚拟机栈就是放这个玩意的,每一个方法从调用到执行完成的过程,对应着一个栈帧在虚拟机栈中入栈到出栈的过程
局部变量表存放了编译期可知的的各种基本数据类型和对象引用类型,所以局部变量表的内存空间在编译期就完成了分配,当前进入一个方法时,这个方法需要在帧中分配多大的空间是完全确定的,在方法运行期间不会改变这个大小
可抛出StackOverflowError、OutOfMemoryError异常
本地方法栈和虚拟机栈作用基本上一样,只是虚拟机栈是用为Java方法服务的,地方法栈是为Native服务的。
线程共享。在虚拟机启动时创建。这个区域的唯一目的就是用来存放对象实例。Java堆是垃圾回收器管理的主要区域。目前的垃圾回收器大都是采用分代回收,所有Java堆分为新生代和老年代,新生代又分为Eden空间、From Survivor和To Survivor空间。Java垃圾回收下篇再讲
可抛出OutOfMemoryError异常
线程共享。用来存储已经被虚拟机加载的类信息、常亮、静态变量、及时编译器编译后的代码。
可抛出OutOfMemoryError异常
上面就是Java的内存区域划分了,我们平常堆jvm调优,上线的时候一般是调整堆内存的大小。初始分配堆内存默认是物理内存的1/64,可以通过-Xms进行设置。最大可分配的默认是物理内存的1/4,可以通过-Xmx进行设置。当初始分配内存不够用时就会扩容,扩容也是消耗性能的操作,所以上线时可以把初始分配内存调到和最大可分配内存差不多大小。
public static void main(String[] args) { Runtime runtime=Runtime.getRuntime(); System.out.println(runtime.maxMemory()); System.out.println(runtime.totalMemory()); } //我电脑内存是8G //maxMemory 1908932608 1.7G左右 //totalMemory 128974848 123M左右复制代码
微信公众号:易大师的小屋