加入收藏 | 设为首页 | 会员中心 | 我要投稿 衡阳站长网 (https://www.0734zz.cn/)- 数据集成、设备管理、备份、数据加密、智能搜索!
当前位置: 首页 > 综合聚焦 > 资源网站 > 空间 > 正文

程序员从宏观、微观角度浅析JVM虚拟机!

发布时间:2019-03-21 00:12:46 所属栏目:空间 来源:架构月亮姨
导读:1.问题 JAVA文本文件如何被翻译成CLASS二进制文件? 如何理解CLASS文件的组成结构? 虚拟机如何加载使用类文件的生命周期? 虚拟机系列诊断工具如何使用? 虚拟机内存淘汰机制? 虚拟机指令集架构? 2.关键词 编译,魔数,常量池,字面量,数据表,堆栈,方法区

我们先观察AddImpl.class常量池,分析第1张表的表结构。查表可知紧接着表个数后面的u1位置为0A,转换为十进制为10,该表类型为CONSTANT_Methodref_info,观察表结构可知接下来的两个u2位置属于该表的字段,这两个字段都是表索引类型,0x0003表示引用第3个表,0x0013表示引用第19个表。

然后该表结束紧接着是第2张表第一个表,该表tag为07是CONSTANT_Class_info类型,第二个空间为u2的字段值为0x0014,引用第20个表。

接着分析第3张表,根据同样的方法,一直可以把常量池的表结构分析完。常量池的作用就是把源代码所有文本数据都集中在常量池这个区间位置内,里面各个表之间相互引用,统一管理文本数据。由于表之间的引用,最后文本数据都是存放在CONSTANT_Class_info表里面,而该表规定文本长度的字段length空间是u2类型,占用2个字节,空间2的16次方,65536/1024=64K,所以java的变量或方法名大小不能超过64K。

4.2.4 访问标志

修饰类或接口的限定标志

在常量池结束后紧接着2个字节的访问标志,共32个标志位。

4.2.5 类/父类/接口索引集合

类索引、父类索引与接口索引集合:指向常量池的CONSTANT_Class_info表,再由CONSTANT_Class_info表里面的index指向特定CONSTANT_Utf8_info表的bytes字段的字面量。

4.5.6 字段表集合

字段表集合:

字段表结构如下

数组用 [ 表示,字段表用来表示类里面所有变量(不包括方法里面的局部变量)

4.5.7 方法表集合

方法表集合:

方法表结构如下

4.5.8 属性表集合

属性表集合

方法体里面的内容编译为Code属性,code表结构如下

Code,Exceptions,LineNumberTable,LocalVariableTable,SourceFile,ConstantValue,InnerClasses,Deprecated,Synthetic

class文件就像是一个产品的模具,把模具制造出来的过程就是把class加载到jvm内存的过程,然后jvm再照着class模具的样子印出对象来。重点在于模具的设计,其实模具被生产出来也是需要它本身有一套模具。这就是class严格的结构规范,class文件结构规范给出了各个方面的要求,只有按照这个要求造出来的模具才是可用的,才可以被用来制造产品,不然连产品线都上不去,就如同jvm判断class不符合规范而拒绝加载。

5.类文件生命周期

类加载时机

类初始化的时机,大部分为被动初始化,用不到的时候都不会初始化。

类加载过程

  • 加载:全限定名检索二进制字节流(不止class文件)->读取至方法区->在堆上生成class对应的对象
  • 验证:文件格式验证(符合class文件规范)->元数据验证(语义分析)->字节码验证(方法体校验)->符号引用验证。可以用-Xverify:none来跳过类加载验证
  • 准备:类变量分配内存设置初值,并未进行赋值操作
  • 解析:针对类接口,字段,方法的符合引用进行解析匹配。类解析,,接口解析,字段解析,类方法解析,接口方法解析,
  • 初始化:执行类构造器

()方法,按源码顺序执行所有static的语句。没有静态变量或者static语句的类将不会有()。

类加载器

启动类加载器,扩展类加载器,应用程序类加载器

类加载器采用双亲委派机制来读取类文件,破坏双亲委派模型如:OSGI服务由自定义类加载器机制实现。每个OSGI模块(Bundle)都有自己的加载器

6.虚拟机诊断工具

虚拟机性能监控与故障处理工具,给一个系统定位问题的时候,知识,经验是基础,数据是依据,工具就是处理数据的手段。

JDK的命令行工具

  • 虚拟机进程状况工具:jps -lvm
  • 虚拟机统计信息监视工具:jstat -gc pid interval count
  • java配置信息工具:jinfo -flag pid
  • java内存映像工具:jmap -dump:format=b,file=java.bin pid

生成堆转储文件

  • 虚拟机堆转储快照分析工具:jhat file 分析堆转储文件,通过浏览器访问分析文件
  • java堆栈跟踪工具:jstack [ option ] vmid

用于生成虚拟机当前时刻的线程快照threaddump或者Javacore

JDK的可视化工具

  • jconsole
  • jvisualvm

7.虚拟机内存淘汰机制

本节从宏观的角度讲解JVM内存结构、内存分配运行策略,垃圾回收机制。

7.1虚拟机内存分布

java内存区域与内存溢出

jvm内存区域:方法区,虚拟机栈,本地方法栈,堆,程序计数器;

  • 程序计数器:字节码行号指示器,每个线程需要一个程序计数器
  • 虚拟机栈:方法执行时创建栈帧(存储局部变量,操作栈,动态链接,方法出口)编译时期就能确定占用空间大小,线程请求的栈深度超过jvm运行深度时抛StackOverflowError,当jvm栈无法申请到空闲内存时抛OutOfMemoryError,通过-Xss,-Xsx来配置初始内存
  • 本地方法栈:执行本地方法,如操作系统api接口
  • 堆:存放对象的空间,通过-Xmx,-Xms配置堆大小,当堆无法申请到内存时抛OutOfMemoryError
  • 方法区:存储类数据,常量,常量池,静态变量,通过MaxPermSize参数配置
  • 对象访问:初始化一个对象,其引用存放于栈帧,对象存放于堆内存,对象包含属性信息和该对象父类、接口等类型数据(该类型数据存储在方法区空间,对象拥有类型数据的地址)

7.2内存回收算法

内存回收概述:

虚拟机栈、本地栈和程序计数器在编译完毕后已经可以确定所需内存空间,程序执行完毕后也会自动释放所有内存空间,所以不需要进行动态回收优化。

jvm内存调优主要针对堆和方法区两大区域的内存。

引用:强Strong,软sfot,弱weak,虚phantom,强引用不会回收,软引用在内存达到溢出边界时回收,弱引用在每次回收周期时回收,虚引用专门被标记为回收对象。

(编辑:衡阳站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

推荐文章
    热点阅读