JVM内存空间详解&实例分析

1、介绍

    Java不需要开发人员来显示分配内存,而是由JVM来自动管理内存的分配和回收(垃圾回收GC),但由此带来的负面影响有可能是在不知不觉中浪费了很多内存或者造成内存泄漏。因此,作为开发人员而言,不能因为JVM自动内存管理机制就不掌握内存分配和回收的知识了。

 

 

2、内存空间

    分析JVM的内存结构,主要是分析JVM运行时数据区,具体划分成5个部分:方法区、堆、虚拟机栈、本地方法栈和程序计数器。

 

2.1 方法区

    方法区是各个线程共享的内存区域,可以被描述为堆的一个逻辑部分。

    方法区主要存放了需要加载的类的信息(名称、修饰符等)、类中的静态变量、类中定义为final类型的常量、类中的field信息、类中的方法信息、即时编译器编译后的代码等数据。在HotSpot中采用永久代的方法来实现方法区,而其他虚拟机(比如IBM J9等)是不存在永久代的。

    Java7中已经将运行时常量池从永久代移除,在堆中专门开辟了一块区域存放运行时常量池。

    Java8中,已经彻底没有了永久代,将方法区直接放在一个与堆不相连的本地内存区域,这个区域叫做元空间。

 

什么是元空间?

    元空间的本质和永久代类似,都是对JVM规范中方法区的实现,不过元空间和永久代最大的区别在于:元空间并不在虚拟机中而是直接使用本地内存。因此在默认情况下,元空间的大小仅受本地内存的限制,但是可以通过以下参数来指定元空间的大小:

-XX:MetaspaceSize,初始空间大小。-XX:MaxMetaspaceSize,最大空间,默认是没有限制的。

2.1.1运行时常量池

    运行时常量池是方法区的一部分,也是线程共享的。

    Class文件中除了有类的版本、字段、方法、接口等信息外,还有一项信息是常量池,用于存放编译期生成的各种字面常量和符号引用,这部分内容在类加载后存放到方法区的常量池中。

    static修饰的静态变量也存放在方法区中,但是不再常量池中(不能修饰局部变量),不能再一个方法内部定义static变量(final可以),只能定义为成员变量。

 

2.2 虚拟机栈

    Java虚拟机栈是线程私有的。虚拟机栈描述的是Java方法执行时的内存模型,即:每个方法被执行的时候都会同时创建一个栈帧,用于存放局部变量表、操作数栈、动态链接、返回地址等信息。每个方法被调用直至执行完成的过程就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。

    Java虚拟机栈不存在垃圾回收的问题,只要线程一结束该栈就释放,其生命周期和线程相同

    Java虚拟机规范中对该区域规定了两种异常情况:

    1)如果线程请求的深度大于虚拟机所允许的深度,栈溢出。比如递归的时候,可能会抛出StackOverflowError异常。

    2)虚拟机栈动态拓展无法申请到足够的内存时,会抛出OutOfMemoryError异常。

注意:

    当方法传递参数时实际上是一个方法将自己栈帧中局部变量表的副本传递给另一个方法栈帧中的局部变量表(注意是副本,不是其本身),不管数据类型是什么(基本类型、引用类型)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值