当前位置: 首页 > news >正文

方法区讲解

在这里插入图片描述
  栈、堆、方法区三者之间的关系如上图所示, 第一个Student代表类型,存放在方法区中, student 变量是在虚拟机栈中,最后 new 出来的Student对象放在堆中。本篇主要讲一下有关方法区中的知识。

文章目录

    • 概念
    • 方法区的内部结构
    • 方法区的变化

概念

  方法区是各个线程共享的运行时内存区域,它用来存储每一个类的结构信息,比如:运行时常量池、字段、方法数据、构造方法等。方法区是在虚拟机启动时就创建完成了,且在实际内存空间上不是连续的。虽然方法区在逻辑上属于堆的一部分(原因是二者在垃圾回收、内存分配上很相似),但实际上方法区是独立于java堆的内存空间,二者存放的内容是不一样的。需要注意的是:
  1、方法区与堆一样,是各个线程共享的内存区域。
  2、方法区在jvm启动的时候被创建,并且它实际的物理内存空间和虚拟机堆区一样都可以不是连续的。
  3、方法区的大小和堆空间一样,可以选择固定大小或者扩展,它的大小可以决定系统保存多少个类,如果系统定义了太多的类,会导致方法区oom。(加载大量的第三方jar包,tomcat部署的工程过多,大量动态地生成反射类。)

方法区的内部结构

  当java源代码编译成class文件,class文件被加载到运行时数据区后,class文件中的一部分信息会加载到方法区中,比如类class、接口interface、枚举enum以及运行时常量池等类型信息。
下面是方法区存放的一些内容:
一、类型信息
  当加载一个class时,方法区需存放下面内容:
  1、完整有效的类名,包括包名和类名。
  2、直接父类的完整有效名。
  3、访问修饰符(public、abstract)
  4、直接接口的列表

二、域信息
  域信息包括域名称、域类型、域修饰符。

三、方法信息
  1、方法名称
  2、方法的返回类型
  3、方法参数的数量和类型
  4、方法的访问修饰符
  5、方法的字节码、操作数栈深度、局部变量表大小。
  6、异常表

四、类变量和类常量
  类变量是static修饰的成员变量,它可以看成是和类一个级别的,随着类加载而加载,类变量被类的所有实例共享。在jdk7之前类变量也是方法区的一部分,jdk7以及以后放到了堆空间。用final static修饰的成员变量叫静态常量,静态常量和静态变量的区别是静态常量在编译期就已经为其赋值。

五、常量池和运行时常量池
  常量池(constant pool)是class 中的信息,当class 文件加载到内存中时,方法区会存放class文件的常量池信息,这时候常量池就变成了运行时常量池。
  一个java应用程序中所有java类的常量池组装成了jvm中最大的运行时常量池。常量池中包含数据类型有:数值、字符串值、类引用、字段引用、方法引用。
  常量池是class文件的一部分,用于存放编译期间生成的各种字面量和符号引用,这部分内容在类加载之后就放到了方法区中的运行时常量池内。
  虚拟机加载类或接口之后,就会创建对应的运行时常量池(也就是说每一个类有一个常量池,加载后对应一个运行时常量池)。之所以叫做运行时常量池,是因为它除了包含编译期间的常量,还包含运行时解析后获得的方法或字段引用。最常见的就是String 的intern()方法。

方法区的变化

  在jdk7及以前,习惯上把方法区称为永久代(因为里面的东西基本是不会变的,只有Full Gc的时候才会清除一下),在jdk8开始以及之后,方法区改名为元空间。永久代和元空间的本质类似,都是对jvm中方法区的实现,但是永久代和元空间最大的区别在于元空间不在虚拟机设置的内存中,而是在本地内存中。

  jdk6以及之前:存在永久代,静态变量在永久代中
  jdk7:存在永久代,但已经逐步去除永久代,字符串常量池、静态变量移除,保存在堆中
  jdk8以及以后:无永久代,取而代之的是元空间,字符串常量池、静态变量仍然在堆中。

jdk6的方法区:
在这里插入图片描述
jdk7的方法区:
在这里插入图片描述
  jdk7对字符串常量池的位置进行了调整,因为永久代的回收效率很低,只有在Full GC才会触发,导致字符串常量池回收效率不够高,我们创建的很多字符串并不需要永久保存,如果不回收的话,就会导致永久代内存不足,所以jdk7将字符串放到了堆中,内存就能及时回收利用。
移动静态变量的道理是一样的。

jdk8的方法区:
在这里插入图片描述
  jdk8中的永久代改名为元空间,通过名字可以看出里面放的是一些元数据,就是有关类相关的信息。它最大的好处是占用的是本地内存,并不是堆,从而减少了堆内存的占用。

相关文章:

  • EasyExcel 导出批注信息
  • 【Go】十四、图形验证码、短信验证码、注册接口与redis的简单使用
  • 单片机练习题3
  • 每日优秀影视分享❗❗
  • WPF文本绑定显示格式StringFormat设置-特殊格式时间日期和多数据绑定
  • 原生dom操作快速写入html渲染(insertAdjacentHTML)
  • Cadence:Conformal系列形式验证工具
  • 深入解析Netty的Reactor模型及其实现:详解与代码示例
  • Pikachu靶场--XSS
  • excel数据透视
  • Ubuntu常见命令解释
  • 修改主频睡眠模式停止模式待机模式
  • 第五章重采样方法
  • 牛顿迭代法(求解整数的近似平方根)
  • 网络爬虫中selenium和requests这两个工具有什么区别呢?
  • .pyc 想到的一些问题
  • angular2开源库收集
  • Brief introduction of how to 'Call, Apply and Bind'
  • ES2017异步函数现已正式可用
  • Java 多线程编程之:notify 和 wait 用法
  • Java编程基础24——递归练习
  • JS专题之继承
  • vue-loader 源码解析系列之 selector
  • zookeeper系列(七)实战分布式命名服务
  • 构建工具 - 收藏集 - 掘金
  • 基于 Ueditor 的现代化编辑器 Neditor 1.5.4 发布
  • 优秀架构师必须掌握的架构思维
  • 在GitHub多个账号上使用不同的SSH的配置方法
  • 新年再起“裁员潮”,“钢铁侠”马斯克要一举裁掉SpaceX 600余名员工 ...
  • #git 撤消对文件的更改
  • #中的引用型是什么意识_Java中四种引用有什么区别以及应用场景
  • (1)Map集合 (2)异常机制 (3)File类 (4)I/O流
  • (PySpark)RDD实验实战——取一个数组的中间值
  • (初研) Sentence-embedding fine-tune notebook
  • (多级缓存)缓存同步
  • (二)JAVA使用POI操作excel
  • (附源码)spring boot智能服药提醒app 毕业设计 102151
  • (三)Honghu Cloud云架构一定时调度平台
  • (十)【Jmeter】线程(Threads(Users))之jp@gc - Stepping Thread Group (deprecated)
  • (四)进入MySQL 【事务】
  • (图文详解)小程序AppID申请以及在Hbuilderx中运行
  • (一)Neo4j下载安装以及初次使用
  • (原)本想说脏话,奈何已放下
  • (转)项目管理杂谈-我所期望的新人
  • (转载)OpenStack Hacker养成指南
  • ***详解账号泄露:全球约1亿用户已泄露
  • 、写入Shellcode到注册表上线
  • .net 获取某一天 在当月是 第几周 函数
  • .NET_WebForm_layui控件使用及与webform联合使用
  • .net和jar包windows服务部署
  • .NET开源项目介绍及资源推荐:数据持久层
  • .NET面试题(二)
  • @Slf4j idea标红Cannot resolve symbol ‘log‘
  • [ IOS ] iOS-控制器View的创建和生命周期
  • [ 隧道技术 ] 反弹shell的集中常见方式(四)python反弹shell