方法区
方法区存储什么?
存储已被虚拟机加载的类型信息、常量、静态变量、即时编译期编译后的代码缓存等。
类型信息(类class、接口interface、枚举enum、注解annotation):
这个类型的完整有效名称(包名.类名)
这个类型直接父类的完整有效名(对于interface或是java.lang.Object,都没有父类)
这个类型的修饰符
这个类型直接接口的有序列表
域(Field)信息
域信息包括:域名称、域类型、域修饰符(public、private、protected、static、final、volatile、transient的某个子类)
方法信息
方法名称
方法的返回类型
方法参数的数量和类型
方法的修饰符
方法的字节码、操作数栈、局部变量表及大小
异常表
为什么需要常量池?
一个java源文件中的类、接口,编译后产生一个字节码文件。而java中的字节码需要数据支持,通常这种数据会很大以至于不能直接存到字节码里,换另一种方式,可以存到常量池,这个字节码包含了指向常量池的引用。在动态链接的时候会用到运行时常量池。
什么是运行时常量池?
运行时常量池是方法区的一部分
常量池表示Class文件的一部分,用于存放编译期生成的各种字面量与符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。
运行时常量池,在加载类和接口到虚拟机后,就会创建对应的运行时常量池。
运行时常量池,相对于Class文件常量池的另一重要特征是:具备动态性。
Hotspot中方法区的变化?
jdk1.6及之前:有永久代,静态变量存放在永久代上。
jdk1.7:有永久代,但已经逐步“去永久代”,字符串常量池、静态变量移除,保存在堆中
jdk1.8及以后:无永久代,类型信息、字段、方法、常量保存在本地内存的元空间,但字符串常量池、静态变量仍在堆中

永久代为什么要被元空间替换?
1.为永久代设置空间大小是很难确定的。
元空间和永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制。
2.对永久代进行调优是很困哪的。
字符串常量池为什么要调整?
因为永久代(元空间)的回收效率很低,在Full gc(整堆回收)的时候才会触发。而我们开发中会有大量的字符串被创建,回收效率低,导致永久代内存不足。放到堆里,能及时回收内存。

浙公网安备 33010602011771号