本文首发于微信公众号【猿灯塔】,转载引用请说明出处

今天呢!灯塔君跟大家讲:

深入了解JVM-方法区

当JVM使用类装载器装载某个类时,它首先要定位对应的class文件,然后读入这个class文件,最后,JVM提取该文件的内容信息,并将这些信息存储到方法区,最后返回一个class实例。上面是对类的装载过程作了个简单的描述,看了上面一段文字,也许你会问:方法区是什么?里面存了哪些内容?下面我们将对方法区作一个详细的描述。

方法区是什么?有哪些特点?

方法区是系统分配的一个内存逻辑区域,是用来存储类型信息的(类型信息可理解为类的描述信息)。方法区主要有以下几个特点: 一.方法区是线程安全的。由于所有的线程都共享方法区,所以,方法区里的数据访问必须被设计成线程安全的。例如,假如同时有两个线程都企图访问方法区中的同一个类,而这个类还没有被装入JVM,那么只允许一个线程去装载它,而其它线程必须等待 二.方法区的大小不必是固定的,JVM可根据应用需要动态调整。同时,方法区也不一定是连续的,方法区可以在一个堆(甚至是JVM自己的堆)中自由分配。 三.方法区也可被垃圾收集,当某个类不在被使用(不可触及)时,JVM将卸载这个类,进行垃圾收集

一、方法区里存放的是哪些内容?
1、类型信息

· 类型的全限定名

· 超类的全限定名

· 直接超接口的全限定名

· 类型标志(该类是类类型还是接口类型)

· 类的访问描述符(public、private、default、abstract、final、static)

2、类型的常量池(该部分是独有的,然后运行时,把该部分加载进运行时常量池,当调用时则从符号引用解析为直接引用,但是有些确定的方法会直接转换,比如静态方法,比如构造方法)

存放该类型所用到的常量的有序集合,包括直接常量(如字符串、整数、浮点数的常量)和对其他类型、字段、方法的符号引用。常量池中每一个保存的常量都有一个索引,就像数组中的字段一样。因为常量池中保存中所有类型使用到的类型、字段、方法的符号引用,所以它也是动态连接(栈中对应的方法指向这个引用)的主要对象(在动态链接中起到核心作用)。

3、字段信息(该类声明的所有字段)

· 字段修饰符(public、protect、private、default)

· 字段的类型

· 字段名称

4、方法信息

方法信息中包含类的所有方法,每个方法包含以下信息:

• 方法名 • 方法的返回类型(包括void) • 方法参数的类型、数目以及顺序 • 方法修饰符(public,private,protected,static,final,synchronized,native,abstract) 针对非本地方法,还有些附加方法信息需要存储在方法区内: • 方法字节码 • 方法中局部变量区的大小、方法栈帧 • 异常表

5、类变量(静态变量)

指该类所有对象共享的变量,即使没有任何实例对象时,也可以访问的类变量。它们与类进行绑定。

6、 指向类加载器的引用

每一个被JVM加载的类型,都保存这个类加载器的引用,类加载器动态链接时会用到。

7、指向Class实例的引用

类加载的过程中,虚拟机会创建该类型的Class实例,方法区中必须保存对该对象的引用。通过Class.forName(StringclassName)来查找获得该实例的引用,然后创建该类的对象。

8、方法表

为了提高访问效率,JVM可能会对每个装载的非抽象类,都创建一个数组,数组的每个元素是实例可能调用的方法的直接引用,包括父类中继承过来的方法。这个表在抽象类或者接口中是没有的,类似C++虚函数表vtbl。

二、运行时常量池(Runtime Constant Pool)

Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是运行时常量池,用于存放编译器生成的各种字面常量和符号引用,这部分内容被类加载后进入方法区的运行时常量池中存放。

运行时常量池相对于Class文件常量池的另外一个特征具有动态性,可以在运行期间将新的常量放入池中(典型的如String类的intern()方法)。

运行时常量池是把Class文件常量池加载进来,每个类有一个独立的。刚开始时运行的时候运行时常量池里的链接都是符号链接(只用名字没有实体),跟在Class文件里的一样;只有调用该方法时,才把常量转换成直接引用。然后就可以供给给其他方法调用了。如下3个图:

如果符号引用是在类加载阶段或者第一次使用的时候转化为直接应用,那么这种转换成为静态解析,如果是在运行期间转换为直接引用,那么这种转换就成为动态连接。

例如说加载完Class A之后的Foo.bar()方法等一段时间被调用,A.class文件里就会有对该方法的Method ref常量,是个符号链接(只有名字没有实体),加载到运行时常量池也还是一样是符号链接(符号引用),等真的要调用该方法的时候该常量就会被resolve(解析)为一个直接链接(直接引用))。

(该部分是独有的,然后运行时,把该部分加载进运行时常量池,当调用时则从符号引用解析为直接引用,但是有些确定的方法会直接转换,比如静态方法,比如构造方法)

365天干货不断,可以微信搜索「 猿灯塔」第一时间阅读,回复【资料】【面试】【简历】有我准备的一线大厂面试资料和简历模板

深入了解JVM-方法区的更多相关文章

  1. java虚拟机 jvm 方法区实战

    和java堆一样,方法区是一块所有线程共享的内存区域,用于保存系统的类信息,类的信息有哪些呢.字段.方法.常量池.方法区也有一块内存区域所以方法区的内存大小,决定了系统可以包含多少个类,如果系统类太多 ...

  2. JVM 方法区内存扩大 以及开启GC

    因为应用使用了OSGi框架,<深入理解JAVA虚拟机>中对使用OSGi时可能产生的方法区溢出有所描述 第一部分: 第二部分 可见,OSGi会动态生成大量Class,在OSGi中,即使是同一 ...

  3. jvm 方法区

    方法区在一个jvm实例的内部,类型信息被存储在一个称为方法区的内存逻辑区中.类型信息是由类加载器在类加载时从类文件中提取出来的.类(静态)变量也存储在方法区中. jvm实现的设计者决定了类型信息的内部 ...

  4. Jvm方法区以及static的内存分配图

    前面的几篇都没有太明确地指出 方法区 是什么?现在通过一些资料的收集和学习,下面做一些总结 什么是方法区: 方法区是系统分配的一个内存逻辑区域,是JVM在装载类文件时,用于存储类型信息的(类的描述信息 ...

  5. 99%的人都搞错了的java方法区存储内容,通过可视化工具HSDB和代码示例一次就弄明白了

    https://zhuanlan.zhihu.com/p/269134063  番茄番茄我是西瓜 那是我日夜思念深深爱着的人啊~ 已关注   6 人赞同了该文章 前言 本篇是java内存区域管理系列教 ...

  6. JVM之方法区

     基本特性: 线程共享区域,存储被JVM加载的类信息.常量.静态变量.即时编译器编译的代码等 堆的逻辑部分,不限定方法去内的内存位置和编译代码的管理策略,不限定实现垃圾回收 容量可不定也可动态扩展,不 ...

  7. JVM的堆(heap)、栈(stack)和方法区(method)

    JVM主要由类加载器子系统.运行时数据区(内存空间).执行引擎以及与本地方法接口等组成.其中运行时数据区又由方法区Method Area.堆Heap.Java stack.PC寄存器.本地方法栈组成. ...

  8. [转]JVM 内存初学 (堆(heap)、栈(stack)和方法区(method) )

    这两天看了一下深入浅出JVM这本书,推荐给高级的java程序员去看,对你了解JAVA的底层和运行机制有比较大的帮助.废话不想讲了.入主题: 先了解具体的概念:JAVA的JVM的内存可分为3个区:堆(h ...

  9. 对JVM虚拟机中方法区的理解

    因为jdk8的jvm已经取消了方法区,所以这边先主要介绍jdk8以下版本中方法区相关内容. 1.虚拟机规范中方法区的概念: 原文链接:http://docs.oracle.com/javase/spe ...

  10. [二]Java虚拟机 jvm内存结构 运行时数据内存 class文件与jvm内存结构的映射 jvm数据类型 虚拟机栈 方法区 堆 含义

    前言简介 class文件是源代码经过编译后的一种平台中立的格式 里面包含了虚拟机运行所需要的所有信息,相当于 JVM的机器语言 JVM全称是Java Virtual Machine  ,既然是虚拟机, ...

随机推荐

  1. Java实现 LeetCode 56 合并区间

    56. 合并区间 给出一个区间的集合,请合并所有重叠的区间. 示例 1: 输入: [[1,3],[2,6],[8,10],[15,18]] 输出: [[1,6],[8,10],[15,18]] 解释: ...

  2. Java实现字母去重

    描述 给定一个字符串S,每次操作你可以将其中任意一个字符修改成其他任意字符. 请你计算最少需要多少次操作,才能使得S中不存在两个相邻的相同字符. 输入 只包含小写字母的字符串S. 1 ≤ |S| ≤ ...

  3. java实现拼出漂亮的表格

    /* * 在中文 Windows 环境下,控制台窗口中也可以用特殊符号拼出漂亮的表格来. 比如: ┌─┬─┐ │ │ │ ├─┼─┤ │ │ │ └─┴─┘ 其实,它是由如下的符号拼接的: 左上 = ...

  4. thinkphp5.0使用官方验证码插件

    1.首先使用Composer下载验证码插件. 安装完成后,使用以下命令修改composer配置文件,使用国内镜像.原因你懂的. composer config -g repo.packagist co ...

  5. JavaScript常用项目(更新至19.11.17)

    目录 项目一:鼠标拖动方块 项目二:网页显示键入字母 项目三:实现滚播图 项目四:   本地数据记事本 项目一:鼠标拖动方块 代码: <!DOCTYPE html> <html> ...

  6. 用了一年 TIM 移动版之后,我又换回了手机 QQ

    TIM,是一个很玄学的产品. 讲真,我很不喜欢 QQ 电脑版.一个原因是我很讨厌一直占着右上角这一行为:右上角是给关闭按钮实现盲操用的,QQ 这么一个聊天软件没有这么高的地位:二是我不喜欢它的多窗口: ...

  7. mysql关于group by的用法

    原文:https://blog.csdn.net/u014717572/article/details/80687042 先来看下表1,表名为test: 表1 执行如下SQL语句: SELECT na ...

  8. ZWave对COMAND CLASS的处理流程

    文章主题  在开发一个 ZWave Device 的过程中,对 COMAND CLASS(单词太长了,后面就简写为 CC 啦) 的处理是最基本.最重要的工作.这篇文章以最最简单的 CC:COMMNAD ...

  9. 使用Bundle在Activity中交换数据

    大概过程 编写demo activity_main.xml <?xml version="1.0" encoding="utf-8"?> <R ...

  10. WPF入门(1)

    开始对WPF动手,从0开始一步一步深入学习 1)参考文档:msdn.<WPF编程宝典:使用C#2012和NET 4.5 第4版> 2)开发工具:Microsoft Visual Studi ...