java虚拟机方法区
方法区的基本概念
方法区和堆一样是多个线程共享的,
《java虚拟机规范》中声明,所有的方法区在逻辑上可以看作是堆的一部分,但是一些简单的实现可能不会选择区进行垃圾收集或者压缩,
而对于hotSpot而言,方法区还有一个别名叫做Non-Heap(非堆),目的就是要和堆分开,所以,方法区可以看作是一块独立与堆的内存空间,而且堆的主要目的是存放创建出来的各种对象,方法区里则会有类的信息,从内容来说,也不相同
方法区在jvm启动时被创建,它的实际物理内存空间和java堆区一样都是可以不连续的
方法区的大小和堆空间一样,可以固定大小也可以扩展
方法区的大小决定了系统可以保存多少个类,如果系统定义了太多的类,导致方法去溢出,虚拟机同样会抛出oom:PermGen space 或者oom : Metspace (1.7之前叫做永久代,1.8叫元空间,报的错误也不一样)
关闭jvm就会释放这个区域的内存
1.7之前习惯性的把方法区叫做永久代,1.8使用元空间取代了永久代,(可以把方法区看作是接口,永久代和元空间都是对应的实现)
方法区和永久代并不等价,只是在hotSpot中是等价的,《java虚拟机规范》中并没有规定具体的实现,不同的虚拟机是不一样的,
永久代使用的是虚拟机的内存,内存方面限制较大,容易溢出
元空间采用的是本地内存来实现的,空间更大
设置方法区的大小
jdk1.7的永久代
-XX:PermSize 初始分配空间 ,默认:20.75M
-XX:MaxPermSize 最大空间 ,32位物理机默认64M,64位默认82M
1.8 元空间:因为用的是本地内存,所以和平台有关系
-XX:MetaspaceSize 初始分配空间 ,windows默认21M
-XX:MaxMetaspaceSize 最大空间 ,默认是-1,也就是没有限制
- 对于初始的元空间大小,会被认为是高水位线,一旦触及这个水位线,就会执行Full GC,卸载没用的类,然后重置高水位线,新的高水位线的取值取决于GC回收了多少元空间,如果释放的空间不足,在不超过最大空间时,会适当提高水位线,如果释放空间过多,会降低水位线
- 所以如果初始化水位线设置过低,高水位线会频繁变动,所以建议初始水位线设置一个较高的值
方法区的内部结构
文件被加载到方法区后,会保留是被哪一个类加载器加载的该文件,也算是类的一部分
方法区用于存储已被虚拟机加载的类型信息(类、接口、枚举、注解)、常量、静态变量、即时编译器编译后的代码缓存等
类型信息:对每个加载的类型信息,jvm必须在方法区中存储以下类型信息:
- 这个类型完整有效名称(全名=包名.类名)
- 这个类型直接父类的完整有效名(接口或者object是没有父类的)
- 这个类型的修饰符(public、abstract、final)
- 这个类型直接接口的一个有序列表(可能会实现了多个接口,是一个有序的列表)
域(Feild,俗称属性)信息
- jvm必须在方法区中保存类型的所有域的相关信息以及域的声明顺序
- 域的相关信息包括:域名称、域类型、域修饰符
方法信息:
- 方法名称
- 方法返回类型
- 方法参数的数量、类型(是有序的)
- 方法修饰符
- 方法字节码、操作数栈、局部变量表及其大小
- 异常表(异常开始位置、结束位置等)
non-final的类变量
- 静态变量和类关联在一起,随着类的加载而加载,成为类数据在逻辑上的一部分
- 类变量被所有实例共享
全局常量(final 的 static),在编译的时候就会被分配了
运行时常量池
方法区内部包含了运行时常量池。
字节码文件,包含常量池,把常量池的信息加载到内存后,就叫做运行时常量池
常量池包含了各种字面量和对类型、域和方法的符号引用,也就是一些基本信息
常量池可以看作是一张表,虚拟机指令根据这张表找到要执行的类名、方法名、参数类型、字面量等信息
常量池是字节码文件的一部分,用于存放编译时生成的各种字面量与符号引用,这部分内容在类加载后会存放到方法区的运行时常量池
运行时常量池是方法区的一部分
每个类或接口都会有一个常量池,当中的数据就像数组一样,可以用索引来访问
运行时常量池中,存储的就不是符号引用了,是真实的地址
运行时常量池相较于常量池来说,具备动态性,有可能常量池中并没有相关信息,比如虚方法等
而字符串常量池再1.6的时候是在永久代的,而1.7就转移到了堆中,1.8虽然去除了永久代,改为元空间,但是字符串常量池依然保留在了堆中,而不是方法区
方法区的演变
只有hotspot才有永久代
在jdk1.6之前,有永久代,而且静态变量存放在永久代上(new的对象的实体始终在堆中,引用在永久代)
1.7,依然有永久代,但是已经在逐步去除永久代了,字符串常量池、静态变量等从永久代中移除,转移到堆中
1.8及以后,就没有永久代了,类型信息、字段、方法、常量保存至本地内存的元空间,但是字符串常量池、静态变量依然放在堆中
为什么要用元空间代替永久代
官方给的消息是,jdk8 ,oracle将hotSport 和 JRockit 进行了整合,而 JRockit 是没有永久代的,所以1.8也没有永久代
也有以下原因:
- 永久代的空间大小难以确定,如果动态加载的类太多,会频繁出现错误,而元空间采用的是本地内存,不受虚拟机内存的限制
- 对永久代的调优很难,想要回收类,条件很苛刻(full GC 代价很大)
字符串常量池的变化
jdk 7 将StringTable放到了堆空间,因为永久代的回收效率很低,只有在full gc 是才会触发,而full GC 是老年代、永久代不足时才会触发,这就使得StingTable回收效率不高,而一般开发中通常会有大量的字符串被创建,如果回收效率低,容易导致永久代内存不足,放在堆里。可以及时的回收内存
方法区的垃圾回收
《java虚拟机规范》对方法区的约束是比较宽松的,方法区的垃圾回收,在不同的虚拟机实现是不同的,是可以不进行垃圾回收的
一般来说,方法区的垃圾回收效果是比较困难的,尤其是类型的卸载,条件十分苛刻,但是方法区的回收有时又是非常由必要的,否则有可能会出现内存泄漏
方法区的垃圾回收主要涉及两部分:
- 常量池中废弃的常量:字面量和符号引用
- 字面量:文本字符串、final的常量值 (比较接近java语言层次)
- 符号引用:类、接口的全限定名,字段的名称和描述符,方法的名称和描述符 (属于编译原理的概念)
- 对于常量池的回收策略很明确:只要常量池中的常量没有被任何地方引用,就可以回收
- 不在使用的类型:想要判定类型是否是不在被使用的条件是很苛刻的,需要满足以下全部条件
- 所有的实例都被回收了,且不存在任何子类实例
- 加载该类的类加载器已经被回收了
- 该类的 .class 对象没有被任何地方引用
- 只有全部满足上面的三个条件,才允许被回收,而不是一定会回收
java虚拟机方法区相关推荐
- java 虚拟机_浅谈Java虚拟机内存区
1. Java 虚拟机内存区概述 我们在编写程序时,经常会遇到OOM(out of Memory)以及内存泄漏等问题.为了避免出现这些问题,我们首先必须对JVM的内存划分有个具体的认识.JVM将内存主 ...
- 2021-02-23关于java的方法区,为什么叫方法区,是否与实际用途相悖?
关于java的方法区,为什么叫方法区,是否与实际用途相悖? 在java中,栈中存放的是用来保存方法运行时状态的栈帧,存储了局部变量表,操作数栈等,而方法区存放的是已加载的类的基本信息.常量.静态变量等 ...
- java堆栈方法区_java 栈 ,堆, 方法区
栈的特点如下: 1. 栈描述的是方法执行的内存模型.每个方法被调用都会创建一个栈帧(存储局部变量.操作数.方法出口等) 2. JVM为每个线程创建一个栈,用于存放该线程执行方法的信息(实际参数.局部变 ...
- java虚拟机及加载class文件的原理机制
2019独角兽企业重金招聘Python工程师标准>>> (点击获取更多资料的下载) java 虚拟机 2007年4月23日,14:18:00 | chenweicai ...
- Java虚拟机 和 java虚拟机下的进程
一.什么是Java虚拟机 当你谈到Java虚拟机时,你可能是指: 1.抽象的Java虚拟机规范 2.一个具体的Java虚拟机实现 3.一个运行的Java虚拟机实 ...
- Java虚拟机(九)——方法区
文章目录 堆.栈.方法区的交互关系 线程是否共享: 三者的交互关系: 方法区的理解 方法区的位置 基本理解: 设置方法区大小 JDK7以前 JDK8及以后: 方法区的内部结构 方法区存储什么 类型信息 ...
- JVM-内存区域 堆、方法区,虚拟机栈、程序计数器详解
JVM 把内存分为若干个不同的区域,这些区域有些是线程私有的,有些则是线程共享的,Java 内存区域也叫做运行时数据区,它的具体划分如下: 虚拟机栈 Java 虚拟机栈是线程私有的数据区,Ja ...
- 【JAVA】堆、栈与方法区
一.Java中的内存管理: 1.程序,无论是代码还是数据,都需要存储在内存中,JVM为Java程序提供并管理所需要的内存空间. 2.JVM内存分为堆(heap).栈(stock).方法区(method ...
- 玩点深入的:Java 虚拟机内存结构及编码实战
本文来源:不会coding 了解JVM内存结构的目的 在Java的开发过程中,因为有JVM自动内存管理机制,不再需要像在C.C++开发那样手动释放对象的内存空间,不容易出现内存泄漏和内存溢出的问题. ...
最新文章
- 赢得高薪的锦囊三秘诀
- 牛批了,1行python代码就可实现炫酷可视化
- python列表的实现原理_Python列表对象实现原理
- @RequestBody, @ResponseBody 注解详解
- 阿里云1C2G虚拟机【99/年】羊毛党集合啦!
- mybatis_user_guide(5) 动态 SQL
- 95-10-040-启动-限额管理
- 在SQL SERVER里面用命令查包含某字段的表
- 分享一些不错的sql语句
- ReactJS基础(续)
- OpenGL ES 中的模板测试
- java菜鸟突破面试系列-终章
- 通达OA2017 工作流设计中“退回”功能的升级测试(图文)
- Visio绘图工具,“连接线”命令使用方法
- 有赞订单搜索AKF架构演进之路
- 2014腾讯实习生招聘数组墙算法
- windows10下安装choco
- 2015年京胜杯删数!删数
- 台式计算机碟片怎么安装,怎样用光盘从装台式电脑系统?
- Apache Solr 任意文件读取