本文已参与「新人创作礼」活动,一起开启掘金创作之路。
JVM中方法区概述
一、概述
对于方法区,我们根据官方文档,可以明确的一点是:
==“方法区逻辑上属于堆空间,但是方法区可以不像堆空间一样,进行GC和压缩”所以我们常常将方法区和堆分离开来讨论==。但我们又会在方法区中进行一些垃圾的回收(它不像堆中那么简单和彻底),Java虚拟机规范中对这一块设计规范较为宽松,我们暂且这么认为。
二、方法区内部结构
方法区存储被jvm加载的类型信息、常量、静态变量等数据
1、类型信息
2、域(成员变量/属性)和方法信息
域(File)信息:
方法信息:
3、类加载器信息
方法区中会存储类的加载器,java程序经过静态编译后编程字节码文件(.class)字节码文件会随着某个类加载器加载到JVM的方法区中,一个类只有唯一的一个类加载器。
当对方法区回收时,可对没用的类加载器进行回收。
5、javap -v 字节码文件名.class
在idea中的local中输入:javap -v 字节码文件名.class
可以对字节码文件进行解析,可以查看类、域、方法、常量池信息等。
ps:在输入命令前要使用cd命令进入到文件目录
也可以在idea中安装jclasslib Bytecode viewer插件进行可视化。
三、方法区的垃圾回收
概述中我们讲了方法区可以不实现垃圾回收,其实方法区有一些垃圾回收:
- 常量池中废弃的常量
- 不再使用的类型
说白了,垃圾回收也就是回收类信息和常量池信息!
1、废弃常量
对于废弃常量的回收很简单,只要不使用了(没用任何地方引用),就会被回收。
常量池中主要存放两大类常量——字面量和符号引用:
字面量:
- 文本字符串
- final声明的常量
符号引用:
- 类和接口的全限定名
- 字段的名称和描述符
- 方法的名称和描述符
2、不使用的类型
对于类信息的回收不再那么简单,条件十分苛刻,需要同时满足以下三个条件:
但是我们在大量使用反射、动态代理、CGLib等字节码框架这种频繁自定义类加载的场景中,需要对类信息进行回收,防止对方法区内存造成压力。
参考资料: 尚硅谷宋红康JVM全套讲解.