栈、堆、方法区的交互关系:

设置方法区大小与OOM:
JDK7及以前;

-XX:PermSize=100m -XX;MaxPermSize=100m
JDK8及以后:

-XX:MetaspaceSize=100m -XX:MaxMetaspaceSize=100m
简单谈如何解决OOM问题:

方法区的内存结构:

方法区主要用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等。(域信息和方法信息可以理解为包含在类型信息之中)

类型信息:

域信息:

方法信息:

non-final的类变量:

全局常量:static final
被声明为final的类变量的处理方法则不同,每个全局常量在编译的时候就会被分配了
为什么需要常量池?
在使用一些公共的信息的时候可以直接保存它的引用而不是它本身,让程序本身更小。

运行时常量池是方法区的一部分,运行时常量池相较于常量池而言,具有动态性

方法区的演进细节:
JDK1.6及之前:有永久代,静态变量存放在永久代上
JDK1.7:有永久代,但已经将字符串常量池和静态变量移除,保存在堆中
JDK1.8及以后:无永久代,类型信息、字段、方法、常量保存在本地内存的元空间,但字符串常量池、静态变量仍在堆
图解:



利用元空间替换永久代的原因;
调整StringTable的原因:
Jdk7中将StringTable放到了堆空间中,因为永久代回收效率很低,在fullGC的时候才会触发。而fullGC是老年代空间不足才会触发,这就导致StringTable回收效率不高,放到堆里面,能及时回收内存。
结论:!!!
静态引用对应的对象实体始终都在堆空间,JDK7以后的版本将静态变量(public static int num=10;其中的num)存放在堆中。
方法区(Hotspot虚拟机中为永久代(JDK7及之前)/元空间(JDK8及以后))的垃圾回收:
常量的垃圾回收:

类型的垃圾回收;

常见面试题:

