深圳俄语网站建设,北京市网页设计,建盏产业品牌,专业团队怎样建设网站一.什么是方法区#xff1f;
方法区属于是 JVM 运行时数据区域的一块逻辑区域#xff0c;是各个线程共享的内存区域。
《Java 虚拟机规范》只是规定了有方法区这么个概念和它的作用#xff0c;方法区到底要如何实现那就是虚拟机自己要考虑的事情了。也就是说#xff0c;在…一.什么是方法区
方法区属于是 JVM 运行时数据区域的一块逻辑区域是各个线程共享的内存区域。
《Java 虚拟机规范》只是规定了有方法区这么个概念和它的作用方法区到底要如何实现那就是虚拟机自己要考虑的事情了。也就是说在不同的虚拟机实现上方法区的实现是不同的。
当虚拟机要使用一个类时它需要读取并解析 Class 文件获取相关信息再将信息存入到方法区。方法区会存储已被虚拟机加载的 类信息、字段信息、方法信息、常量、静态变量、即时编译器编译后的代码缓存等数据。
二.方法区和永久代以及元空间有什么关系
Jdk1.6及之前,有永久代(Permenent generation),静态变量存放在永久代上Jdk1.7有永久代,但已经逐步去永久代,字符串常量池,静态变量移除保存在堆上Jdk1.8及之后,没有永久代,类型信息,字段,方法,常量保存在本地内存的元空间中,但是字符串常量池,静态变量仍在堆中.
方法区和永久代以及元空间的关系很像 Java 中接口和类的关系类实现了接口这里的类就可以看作是永久代和元空间接口可以看作是方法区也就是说永久代以及元空间是 HotSpot 虚拟机对虚拟机规范中方法区的两种实现方式。
三.为什么要将永久代 (PermGen) 替换为元空间 (MetaSpace) 呢? 1、整个永久代有一个 JVM 本身设置的固定大小上限无法进行调整而元空间使用的是直接内存受本机可用内存的限制虽然元空间仍旧可能溢出但是比原来出现的几率会更小。 你可以使用 -XXMaxMetaspaceSize 标志设置最大元空间大小默认值为 unlimited这意味着它只受系统内存的限制。-XXMetaspaceSize 调整标志定义元空间的初始大小如果未指定此标志则 Metaspace 将根据运行时的应用程序需求动态地重新调整大小。
2、元空间里面存放的是类的元数据这样加载多少类的元数据就不由 MaxPermSize 控制了, 而由系统的实际可用空间来控制这样能加载的类就更多了。
3、在 JDK8合并 HotSpot 和 JRockit 的代码时, JRockit 从来没有一个叫永久代的东西, 合并之后就没有必要额外的设置这么一个永久代的地方了。
四.什么是运行时常量池
Class 文件中除了有类的版本、字段、方法、接口等描述信息外还有用于存放编译期生成的各种字面量Literal和符号引用Symbolic Reference的常量池表(Constant Pool Table)。常量池表会在类加载后存放到方法区的运行时常量池中。
字面量是源代码中的固定值的表示法即通过字面我们就能知道其值的含义。字面量包括整数、浮点数和字符串字面量符号引用包括类符号引用、字段符号引用、方法符号引用和接口方法符号引用。
运行时常量池的功能类似于传统编程语言的符号表尽管它包含了比典型符号表更广泛的数据。
既然运行时常量池是方法区的一部分自然受到方法区内存的限制当常量池无法再申请到内存时会抛出 OutOfMemoryError 错误。
JDK1.7 及之后版本的 JVM 已经将运行时常量池从方法区中移了出来在 Java 堆Heap中开辟了一块区域存放运行时常量池。
五.字符串常量池有什么作用
字符串常量池 是 JVM 为了提升性能和减少内存消耗针对字符串String 类专门开辟的一块区域主要目的是为了避免字符串的重复创建.
String aa ab; // 放在常量池中
String bb ab; // 从常量池中查找
System.out.println(aabb);// trueJDK1.7 之前运行时常量池逻辑包含字符串常量池存放在方法区。JDK1.7 的时候字符串常量池被从方法区拿到了堆中。
这里的字符串其实就是我们前面提到的字符串字面量。在声明一个字符串字面量时如果字符串常量池中能够找到该字符串字面量则直接返回该引用。如果找不到的话则在常量池中创建该字符串字面量的对象并返回其引用。
六.JDK 1.7 为什么要将字符串常量池移动到堆中
主要是因为永久代方法区实现的 GC 回收效率太低只有在整堆收集 (Full GC)的时候才会被执行 GC。Java 程序中通常会有大量的被创建的字符串等待回收将字符串常量池放到堆中能够更高效及时地回收字符串内存。
总结
一张图片带你看看 JDK1.6 到 JDK1.8 方法区的变化。