《码出高效-Java开发手册》走进JVM有感

走进JVM

字节码

Java 所有的指令有200个左右,一个字节可以存储256种不同的指令信息,一个这样的字节称为字节码(中间码)。在代码的执行过程中,JVM将字节码解释执行,屏蔽对底层操作系统的依赖,JVM 也可以将字节码编译执行,如果是热点代码,会通过JIT 动态地编译为机器码,提高执行效率

字节码主要指令如下:

加载或存储指令

在某个栈帧中,通过指令操作数据在虚拟机栈的局部变量表与操作栈之间来回传输,常用指令如下:

将局部变量加载到操作栈中。

从操作栈顶存储到局部变量表

将常量加载到操作栈顶,这是极为高频使用的指令

运算指令: 对两个操作栈帧上的值进行运算,并把结果写入操作栈顶IADD、IMUL

类型转换指令 显示转换两种不同的数值类型

对象创建于访问指令

创建对象指令 NEW NEWARRAY

访问属性指令 GETFIELD、PUTFIELD 等

检查实例类型指令

操作栈管理指令

出栈指令

赋值栈顶元素并压入栈

方法调用与返回指令

详细见 P125《码出高效: JAVA开发手册》

Java源文件 ----> 词法解析-- token流 -> 语法解析 -----> 语义分析 -----> 生成字节码 ----> 字节码

详细见P126

类加载过程

任何程序都需要加载到内存中才能与CPU进行交流。字节码 .class 文件同样需要家长到内存中,才可以实例化类。ClassLoader 就是提前加载 .class 文件到内存中

过程: 加载、链接、初始化

加载: 读取类文件产生的二进制流,并转为特定的数据结构,初步校验cafe babe 魔法值,常量池、文件长度、是否有父类等,然后创建对应类的实例

链接包括验证、准备、解析三个过程。验证是更详细的校验,比如final 是否合规,类型是否正确、静态变量是否合理等;准备结果是为静态变量分配内存,并设定默认值,解析类和方法确保类与类之间的相互引用正确性,完成内存结构布局

初始化结果,执行类构造器方法,如果赋值运算是通过其他类的静态方法来完成的,那么会马上解析另一个类,在虚拟机栈中执行完毕后通过返回值进行赋值

内存布局

Heap (堆区)

是OOM 故障的主要发源地,它存储着几乎所有的实例对象,堆由垃圾收集器自动回收,堆区各子线程共享使用。通常它的占用的空间是所有内存区域最大的,但是如果无节制的创建实例那么也将会消耗完内存导致OOM。可以在运行时动态的设置它的大小,-Xms256M - Xmx1024M 表示设定初始值和最大值。服务器在运行过程中,退空间不断地扩容和回缩,势必形成不必要的系统压力,所以在线上生产环境中,JVM 的Xms和Xmx 设置为一样大小,避免在GC 后调整堆大小时带来的额外压力。

(下图:这里的放得下指的是当创建一个大对象时候,内存区域是否能够容纳得下)

Metaspace(元空间)

元空间的前身是Perm区(被称为永久代),在JDK7 及之前的版本中才有Perm,现在的版本使用了Metaspace。因为Perm 在某些场景下,如果动态加载类过多,容易产生Perm 区的OOM(为了解决需要设定参数 -XX:MaxPermSize = 1280m),如果部署到新机器上,往往会因为JVM 参数没有修改导致故障再现,不熟悉此应用的人很难排查。所以,元空间就诞生了。元空间在本地内存中分配。

JVM Stack (虚拟机栈)

栈的特性是先进后出的数据结构,JVM 是基于栈结构的院系环境。JVM 中的虚拟机栈是描述Java方法执行的内存区域,它是线程私有的。栈中的元素用于支持虚拟机进行方法调用,每个方法从开始调用到执行完成的过程。就是栈帧从入栈到出栈的过程。活动线程中只有位于栈顶的帧才是有效的,称为当前栈帧。正在执行的方法称为当前方法。

虚拟机栈通过压栈和出栈的方式,对每个方法对应的活动栈帧进行运算处理,方法正常执行结束,肯定会跳转到另一个栈帧上。在执行过程中,如果出现异常,会进行异常回溯,返回地址通过异常处理表确定。

局部变量表: 存放方法参数和局部变量的区域

操作栈 : 一个初始状态为空的桶式结构栈。在方法执行过程中,会有各种指令往栈中写入和提取信息。

动态连接:每一个栈帧包含一个常量池中对当前方法的引用,目的是支持方法调用过程的动态连接

方法返回地址: 方法执行有两种退出情况: 1. 正常退出。2.异常退出。 无论何种退出情况都将返回到方法当前被调用的位置。方法退出的过程相当于弹出当前栈帧。

本地方法栈

Native Method Stack 在JVM内存布局中,也是线程对象私有的。被称为Native 方法服务,线程开始调用本地方法时,会进入一个不再受JVM约束的世界。本地方法可以通过JNI来访问虚拟机运行时的数据区,甚至可以调用寄存器,具有和JVM相同的能力和权限。

程序计数寄存器

每一个线程在创建后,都会产生自己的程序计数器和栈帧,程序计数器用来存放执行指令的偏移量和行号指示器,程序的执行或者恢复都要依赖程序计数器。程序计数器在哥线程之间互不影响,此区域不会发生内存溢出异常。

从线程共享的角度来看,堆空间和元空间都所有线程共享的,而虚拟机栈和本地方法栈,程序计数器是线程内部私有的。

对象实例化

实例化对象过程

确认类元信息是否存在。当JVM接受到new指令时,首先在metaspace 内检查需要创建的类元信息是否存在。若不存在,那么在双亲委派模式下,使用当前类加载器以ClassLoader +包名+类名为key 进行查找对应的.class 文件,如果没有找到文件,则抛出ClassNotFoundException 异常,如果找到,则进行类加载并生成对应的Class 类对象。

分配对象内存。首先计算对象占用空间大小,如果实例成员变量是引用变量,仅分配引用变量空间即可,即4个字节大小,接着在堆中划分一块内存给新对象。在分配内存空间时,需要进行同步操作,比如采用CAS失败重试,区域加锁等方式保证分配操作的原子性。

设定默认值。成员变量值都需要设定默认值,即各种不同形式的零值。

设置对象头。设置新对象的哈希码,GC信息,锁信息,对象所属的类元信息等。这个过程的具体设置方式取决JVM实现。

执行init 方法。初始化成员变量,执行实例化代码块,调用类的构造方法,并把堆内对象的首地址赋值给引用变量。

垃圾回收

Java 会对内存进行自动分配与回收管理,使上层业务更加安全,方便地使用内存实现程序逻辑。GC 主要目的是清除不再使用的对象,自动释放内存。

标记-清除

复制

标记-整理

区分新老年代(分代收集)

但最重要的是不知道哪些技术需要重点掌握,学习时频繁踩坑,最终浪费大量时间,所以有一套实用的视频课程用来跟着学习是非常有必要的。

为了让学习变得轻松、高效,今天给大家免费分享一套阿里架构师传授的一套教学资源。帮助大家在成为架构师的道路上披荆斩棘。

这套视频课程详细讲解了(Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化、分布式架构)等这些成为架构师必备的内容!

而且还把框架需要用到的各种程序进行了打包,根据基础视频可以让你轻松搭建分布式框架环境,像在企业生产环境一样进行学习和实践。

有需要的可以加群:810589193,点击链接加入群聊【Java架构学习交流群】:https://jq.qq.com/?_wv=1027&k=5deQUBl

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,928评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,192评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,468评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,186评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,295评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,374评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,403评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,186评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,610评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,906评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,075评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,755评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,393评论 3 320
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,079评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,313评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,934评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,963评论 2 351

推荐阅读更多精彩内容

  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,221评论 11 349
  • 第二部分 自动内存管理机制 第二章 java内存异常与内存溢出异常 运行数据区域 程序计数器:当前线程所执行的字节...
    小明oh阅读 1,147评论 0 2
  • 这篇文章解释了Java 虚拟机(JVM)的内部架构。下图显示了遵守Java SE 7 规范的典型的 JVM 核心内...
    饮墨飨书阅读 656评论 0 1
  • 每个使用Java的开发者都知道Java字节码是在JRE中运行(JRE: Java 运行时环境)。JVM则是JRE中...
    燕京博士阅读 1,403评论 0 6
  • 这篇文章是我之前翻阅了不少的书籍以及从网络上收集的一些资料的整理,因此不免有一些不准确的地方,同时不同JDK版本的...
    高广超阅读 15,575评论 3 83