JVM内存结构之方法区 ,我们之前在堆区就说过,虽然堆区中包含了(永久代/元空间)但实际上(永久代/元空间)却是独立于堆区的。 对于HotSpot虚拟机而言,方法区还有一个别名叫做Non-Heap (非堆),目的就是要和堆分开。所以,方法区看作是一块独立于Java堆的内存空间。
1.方法区特点
- 方法区(Method Area) 与Java堆- 样,是各个线程共享的内存区域。
- 方法区在JVM启动的时候被创建,并且它的实际的物理内存空间中和Java堆区一样都可以是不连续的。
- 方法区的大小,跟堆空间一样,可以选择固定大小或者可扩展。
- 方法区的大小决定了系统可以保存多少个类,如果系统定义了太多的类,导致方法区溢出,虚拟机同样会抛出内存溢出错误: java. lang. outOfMemoryError :IBermGen space或者java. lang . OutOfMemoryError: Metaspace关闭JVM就会释放这个区域的内存。
2.堆、栈、方法区的交互
下面通过一个创建对象的过程来看一下堆、栈、方法区之间的交互关系。
3.JDK7和JDK8中的方法区
代、元空间二者并不只是名字变了,内部结构也调整了。 元空间的本质和永久代类似,都是对JVM规范中方法区的实现。不过元空间与永久代最大的区别在于:元空间不在虚拟机设置的内存中,而是使用本地内存。
4. JVM设置方法区大小
JDK7及以前
- 通过-XX:PermSize=100m来 设置永久代初始分配空间为100M。默认值是20.75M
- 通过-XX:MaxPermSize=100m来设定永久代最大可分配空间为100M。32位机器默认是64M,64位机器模式是82M
- 当JVM加载的类信息容量超过了这个值,会报异常OutofMemoryError : PermGenspace
JDK8及以后
- 元数据区大小可以使用参数-XX :MetaspaceSize=100m和-XX :MaxMetaspaceSize=100m指定,替代_上述原有的两个参数。
- 默认值依赖于平台。windows下,-XX :MetaspaceSize是21M,-XX:MaxMetaspaceSize的值是-1,即没有限制。
- 与永久代不同,如果不指定大小,默认情况下,虚拟机会耗尽所有的可用系统内存。如果元数据区发生溢出,虚拟机一样会拋出异常OutOfMemoryError: Metaspace
- -XX:MetaspaceSize: 设置初始的元空间大小。对于一个64位的服务器端JVM来说,其默认的-XX :MetaspaceSize值为21MB。这就是初始的高水位线,一旦触及这个水位线,Full GC将会被触发并卸载没用的类(即这些类对应的类加载器不再存活) ,然后这个高水位线将会重置。新的高水位线的值取决于GC后释放了多少元空间。如果释放的空间不足,那么在不超过MaxMetaspaceSize时,适当提高该值。如果释放空间过多,则适当降低该值。
- 如果初始化的高水位线设置过低,上 述高水位线调整情况会发生很多次。通过垃圾回收器的日志可以观察到Full GC多次调用。为了避免频繁地GC,建议将-XX :MetaspaceSize设置为-一个相对较高的值。
5. 方法区内部结构
《深入理解Java虚拟机》书中对方法区(Method Area) 存储内容描述如下:它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等。
类型信息
对每个加载的类型(类class、接口interface、枚举enum、注解annotation) ,JVM必须在方法区中存储以下类型信息:
- 这个类型的完整有效名称(全名=包名.类名) .
- 这个类型直接父类的完整有效名(对于interface或是java. lang . object,都没有父类)
- 这个类型的修饰符(public, abstract, fina1的某个子集)
- 这个类型直接接口的一个有序列表。
方法信息
JVM必须保存所有方法的以下信息,同域信息一样包括声明顺序:
- 方法名称法
- 方法的返回类型(或void)
- 方法参数的数量和类型(按顺序)
- 方法的修饰符(public, private, protected, static, final,synchronized, native, abstract的一个子集)
- 方法的字节码(bytecodes)、操作数栈、局部变量表及大小(abstract和native方法除外)
- 异常表(abstract和native方 法除外)每个异常处理的开始位置、结束位置、代码处理在程序计数器中的偏移地址、被捕获的异常类的常量池索引
运行时常量池
- 常量池表( Constant Pool Table) 是Class文件的一 部分,用于存放编译期生成的各种字面量与符号引用(常量池),这部分内容将在类加载后存放到方法区的运行时常量池中。
- 运行时常量池中包含多种不同的常量,包括编译期就已经明确的数值字面量,也包括到运行期解析后才能够获得的方法或者字段引用。此时不再是常量池中的符号地址了,这里换为真实地址。
- 运行时常量池类似:于传统编程语言中的符号表(symboltable), 但是它所包含的数据却比符号表要更加丰富一些。
静态变量
标签云
ajax AOP Bootstrap cdn Chevereto CSS Docker Editormd GC Github Hexo IDEA JavaScript jsDeliver JS樱花特效 JVM Linux Live2D markdown Maven MyBatis MyBatis-plus MySQL Navicat Oracle Pictures QQ Sakura SEO Spring Boot Spring Cloud Spring Cloud Alibaba SpringMVC Thymeleaf Vue Web WebSocket Wechat Social WordPress Yoast SEO 代理 分页 图床 小幸运 通信原理
Comments | NOTHING