8. 方法区

8.1 方法区的基本理解

  • 方法区(Method Area)与Java堆一样,是各个线程共享的内存区域。
  • 方法区在JVM启动的时候被创建,并且它的实际的物理内存空间中和Java堆区一样都可以是不连续的。
  • 方法区的大小,跟堆空间一样,可以选择固定大小或者可扩展。
  • 方法区的大小决定了系统可以保存多少个类,如果系统定义了太多的类,导致方法区溢出,虚拟机同样会抛出内存溢出错误: java.lang.outOfMemory PermGen space或者java.lang.outOfMemoryError: Metaspace
  • 关闭JVM就会释放这个区域的内存。

JDK8放弃永久代的概念,使用JRockit的元空间来代替。元空间不再虚拟机设置的内存中,而是使用本地内存

8.2 方法区的大小的设置与OOM

  • jdk7及以前:

    • 通过-XX:PermSize来设置永久代初始分配空间。默认值是20.75M
    • -XX:MaxPernSize来设定永久代最大可分配空间。32位机器默认是64M,64位机器模式是82M
    • 当JVM加载的类信息容量超过了这个值,会报异常outOfMemoryError:PermGenspace。
  • jdk8及以后:

    • 元数据区大小可以使用参数-XX:MetaspaceSize-XX:MaxMetaspaceSize指定,替代上述原有的两个参数。
    • 默认值依赖于平台。windows下,-XX:MetaspaceSize是21M,-XX:MaxMetaspaceSize的值是-1,即没有限制。
    • -XX:MetaspaceSize设置的是初始的高水位线,触及这个水位线FullGC被触发,根据释放的空间调整高水位线,如果初始化的高水位线设置过低,上述高水位线调整情况会发生很多次。通过垃圾回收器的日志可以观察到Full GC多次调用。为了避免频繁地GC,建议将-XX:MetaspaceSize设置为一个相对较高的值。

注意用等号赋值(永久代或者元空间)设置,例如:-XX:MetaspaceSize=100M

8.3 方法区

  • 方法区主要存储虚拟机加载的类型信息、常量、静态变量、及时编译器编译后的代码缓存、类加载器。

类型信息:实现的接口序列、修饰符、直接父类的完整有效名、类的完整有效名等

域(filed属性)信息:修饰符、名称等

方法的信息:名称、返回类型、参数数量和类型、方法的修饰符等

8.4 常量池

字节码:一个有效的字节码文件中除了包含类的版本信息、字段、方法以及接口等描述信息外,还包含一项信息那就是常量池表(Constant Pool Table),包括各种字面量和对类型、域和方法的符号引用。

8.5 运行时常量池

  • 运行时常量池(Runtime Constant Poo1)是方法区的一部分。
  • 常量池表(Constant Pool Table)是class文件的一部分,用于存放编译期生成的各种字面量与符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。

只有HotSpot才有永久代

8.6 方法区的演进

版本 变化
jdk1.6及以前 有永久代,静态变量存放在永久代上
jdk1.7 有永久代,但己经逐步“去永久代”,字符串常量池、静态变量移除,保存在堆中
jdk1.8及之后 无永久代,类型信息、字段、方法、常量保存在本地内存的元空间,但字符串常量池、静态变量仍在堆里

java虚拟机JVM方法区(OOM、垃圾回收等)

永久代为什么被替换?

  1. 为永久代设置空间大小是很难确定的。
  2. 对永久代进行调优是很困难的

方法区的垃圾回收主要有什么?

  1. 常量池中废弃的常量
  2. 不再使用的类型

判断常量不会被使用是很费时间的,这样调优也就比较困难

StringTable为什么要调整?

  • jdk7中将stringTable放到了堆空间中。因为永久代的回收效率很低,在full ge的时候才会触发。而full gc是老年代的空间不足、永久代不足时才会触发。这就导致stringTable回收效率不高。而我们开发中会有大量的字符串被创建,回收效率低,导致永久代内存不足。放到堆里,能及时回收内存。

8.7 方法区的垃圾收集

  • 如何判断一个常量是否被‘废弃’?

    1. 该类所有的实例都已经被回收,也就是Java堆中不存在该类及其任何派生子类的实例。
    2. 加载该类的类加载器已经被回收,这个条件除非是经过精心设计的可替换类加载器的场景,如OSGi、JSP的重加载等,否则通常是很难达成的。
    3. 该类对应的java.lang.class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。

    并不是满足上述三个条件就会被回收,而是允许被回收。HotSpot虚拟机提供了-Xnoclassgc参数进行控制

  • 方法区的垃圾主要回收:常量池中废弃的常量和不再使用的类型。

java虚拟机JVM方法区(OOM、垃圾回收等)

相关文章:

  • 2021-10-01
  • 2021-09-25
  • 2021-11-24
  • 2021-10-15
  • 2021-09-21
  • 2022-02-02
  • 2021-11-06
  • 2021-10-19
猜你喜欢
  • 2021-08-10
  • 2021-10-17
  • 2021-07-19
  • 2021-05-02
  • 2022-12-23
  • 2022-03-05
  • 2021-09-15
相关资源
相似解决方案