为什么要了解虚拟机
JVM 不单单只支持 Java 语言,也支持其他语言(Scala、Kotlin、Groovy 等等) 区块链 2.0--以太坊(比特币是区块链 1.0) 中提供了 EVM 的虚拟机,它的实现和 JVM 类似,基于栈、生成脚本编译成字节码来执行。知 识通用。(理论大于实际)
虚拟机历史
了解即可,无需关注 解释执行和编译执行(针对字节码的执行) 解释执行就是边翻译为机器码边执行、即时编译(编译执行)就是先将一个方法中的所有字节码全部编译成机器码之后再执行。 Hotspot 采用的是先解释执行,到了一定时机后热点代码(多次执行、循环等)再翻译成机器码 热点代码探测技术(通过执行计数器找到最有编译价值的代码,如果代码用得非常频繁,就会把这些代码编译成本地代码)。 JRockit 采取的方法是在执行 class 时直接编译为机器码(Java 程序启动速度会比较慢) J9 和 Hotspot 比较接近,主要是用在 IBM 产品(IBMWebSphere 和 IBM 的 AIX 平台上),华为有的项目用的 J9。 谷歌:GoogleAndroidDalivkVM:使用的寄存器架构,执行 dex(DalvikExecutable)通过 class 转化而来。
未来的 Java 技术
模块化:OSGI(动态化、模块化),应用层面就是微服务,互联网的发展方向 混合语言:多个语言都可以运行在 JVM 中,google 的 Kotlin 成为了 Android 的官方语言。Scala(Kafka)
多核并行:CPU 从高频次转变为多核心,多核时代。JDK1.7 引入了 Fork/Join,JDK1.8 提出 lambda 表达式(函数式编程天生适合并行运 行) 丰富语法:JDK5 提出自动装箱、泛型(并发编程讲到)、动态注解等语法。JDK7 二进制原生支持。try-catch-finally 至 try-with-resource 64 位:虽然同样的程序 64 位内存消耗比 32 位要多一点,但是支持内存大,所以虚拟机都会完全过渡到 64 位,32 位的 JVM 有 4G 的 堆大小限制。 更强的垃圾回收器(现在主流 CMS、G1):JDK11 –ZGC(暂停时间不超过 10 毫秒,且不会随着堆的增加而增加,TB 级别的堆回收)): 有色指针、加载屏障。JDK12 支持并发类卸载,进一步缩短暂停时间 JDK13(计划于 2019 年 9 月)将最大堆大小从 4TB 增加到 16TB
JavaSE 体系架构
JavaSE,Java 平台标准版,为 JavaEE 和 JavaME 提供了基础。 JDK:Java 开发工具包,JDK 是 JRE 的超集,包含 JRE 中的所有内容,以及开发程序所需的编译器和调试程序等工具。 JRE:JavaSE 运行时环境 ,提供库、Java 虚拟机和其他组件来运行用 Java 编程语言编写的程序。主要类库,包括:程序部署发布、用 户界面工具类、继承库、其他基础库,语言和工具基础库 JVM:java 虚拟机,负责 JavaSE 平台的硬件和操作系统无关性、编译执行代码(字节码)和平台安全性
运行时数据区域
这个是抽象概念,内部实现依赖寄存器、高速缓存、主内存(具体要分析 JVM 源码 C++语言实现,没必要看) 计算机的运行=指令+数据,指令用于执行方法的,数据用于存放数据和对象的。 虚拟机栈----执行 java 方法、本地方法栈---执行本地方法、程序计数器---程序执行的计数器 Java 中的数据:变量、常量、对象、数组相关。
程序计数器
较小的内存空间,当前线程执行的字节码的行号指示器;各线程之间独立存储,互不影响(面试可能问到为什么需要) 如果线程正在执行的是一个 Java 方法,则指明当前线程执行的代字节码行数 如果正在执行的是 Natvie 方法,这个计数器值则为空(Undefined) 此内存区域是唯一一个不会出现 OutOfMemoryError 情况的区域。
虚拟机栈(JVM 后续的执行子程序有详细的见解)

iload_1 第二个 int 型局部变量进栈
bipush 将一个 byte 型常量值推送至栈顶
isub 栈顶两int型数值相减,并且结果进栈
istore_1 将栈顶int型数值存入第二个局部变量

栈: 数据结构的特点和 java 中方法中调用方法的特性一致。(为什么 JVM 使用栈 –演示代码 StackFilo)

虚拟机栈:

异常: 线程请求的栈深度大于虚拟机所允许的深度:StackOverflowError

JVM 动态扩展时无法申请到足够的内存时:OutOfMemoryError

虚拟机栈: 每个线程私有的,线程在运行时,在执行每个方法的时候都会打包成一个栈帧,存储了局部变量表,操作数栈,动态链接,方法出口等信息,然后放入 栈。每个时刻正在执行的当前方法就是虚拟机栈顶的栈桢。方法的执行就对应着栈帧在虚拟机栈中入栈和出栈的过程。 栈的大小缺省为 1M,可用参数 –Xss 调整大小,例如-Xss256k

在编译程序代码的时候,栈帧中需要多大的局部变量表,多深的操作数栈都已经完全确定了,并且写入到方法表的 Code 属性之中,因此一个栈帧需要分 配多少内存,不会受到程序运行期变量数据的影响,而仅仅取决于具体的虚拟机实现。

局部变量表:顾名思义就是局部变量的表,用于存放我们的局部变量的。首先它是一个 32 位的长度,主要存放我们的 Java 的八大基础数据类型,一般 32 位就可以存放下,如果是 64 位的就使用高低位占用两个也可以存放下,如果是局部的一些对象,比如我们的 Object 对象,我们只需要存放它的一个引用 地址即可。(基本数据类型、对象引用、returnAddress 类型)

操作数据栈:存放我们方法执行的操作数的,它就是一个栈,先进后出的栈结构,操作数栈,就是用来操作的,操作的的元素可以是任意的 java 数据类 型,所以我们知道一个方法刚刚开始的时候,这个方法的操作数栈就是空的,操作数栈运行方法是会一直运行入栈/出栈的操作

动态连接:Java 语言特性多态(需要类加载、运行时才能确定具体的方法,后续有详细的讲解)

返回地址:

正常返回(调用程序计数器中的地址作为返回)

三步曲:

恢复上层方法的局部变量表和操作数栈、

把返回值(如果有的话)压入调用者栈帧的操作数栈中、

调整 PC 计数器的值以指向方法调用指令后面的一条指令、

异常的话(通过异常处理器表<非栈帧中的>来确定)
本地方法栈
各虚拟机自由实现,本地方法栈 native 方法调用 JNI 到了底层的 C/C++(c/c++可以触发汇编语言,然后驱动硬件)
线程共享的区域
类信息: 类的完整有效名、返回值类型、修饰符(public,private...)、变量名、方法名、方法代码、这个类型直接父类的完整有效名(除非这个 类型是 interface 或是 java.lang.Object,两种情况下都没有父类)、类的直接接口的一个有序列表
方法区/永久代
用于存储已经被虚拟机加载的类信息,常量("zdy","123"等),静态变量(static 变量)等数据,可用以下参数调整:

jdk1.7 及以前:-XX:PermSize;-XX:MaxPermSize;

jdk1.8 以后:-XX:MetaspaceSize; -XX:MaxMetaspaceSize

jdk1.8 以后大小就只受本机总内存的限制

如:-XX:MaxMetaspaceSize=3M

几乎所有对象都分配在这里,也是垃圾回收发生的主要区域,可用以下参数调整:

-Xms:堆的最小值;

-Xmx:堆的最大值;

-Xmn:新生代的大小;

-XX:NewSize;新生代最小值;

-XX:MaxNewSize:新生代最大值;

例如-Xmx256m
运行时常量池
符号引用(一个概念)
一个 java 类(假设为 People 类)被编译成一个 class 文件时,如果 People 类引用了 Tool 类,但是在编译时 People 类并不知道引用类的实际内存地址,因 此只能使用符号引用来代替。 而在类装载器装载 People 类时,此时可以通过虚拟机获取 Tool 类的实际内存地址,因此便可以既将符号 org.simple.Tool 替换为 Tool 类的实际内存地址, 及直接引用地址。 即在编译时用符号引用来代替引用类,在加载时再通过虚拟机获取该引用类的实际地址. 以一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用时能无歧义地定位到目标即可。符号引用与虚拟机实现的内存布局是无关的, 引用的目标不一定已经加载到内存中。
字面量
文本字符串 Stringa="abc",这个 abc 就是字面量 八种基本类型 inta=1; 这个 1 就是字面量 声明为 final 的常量
直接内存
使用 Native 函数库直接分配堆外内存(NIO)

并不是 JVM 运行时数据区域的一部分,但是会被频繁使用(可以通过-XX:MaxDirectMemorySize 来设置(默认与堆内存最大值一样,也会 出现 OOM 异常)

避免了在 Java 堆和 Native 堆中来回复制数据,能够提高效率

测试用例 JavaStack:设置 JVM 参数-Xmx100m,运行异常,因为如果没设置-XX:MaxDirectMemorySize,则默认与-Xmx 参数值相同,分 配 128M 直接内存超出限制范围
站在线程角度来看
虚拟机栈、本地方法栈、程序计数器三个区域的生命周期和线程相同。 线程共享区域:就复杂多了,后续完善
深入辨析堆和栈
 功能
 以栈帧的方式存储方法调用的过程,并存储方法调用过程中基本数据类型的变量(int、 short、 long、 byte、 float、
double、boolean、char 等)以及对象的引用变量,其内存分配在栈上,变量出了作用域就会自动释放;
 而堆内存用来存储 Java 中的对象。无论是成员变量,局部变量,还是类变量,它们指向的对象都存储在堆内
存中;
 线程独享还是共享
 栈内存归属于单个线程,每个线程都会有一个栈内存,其存储的变量只能在其所属线程中可见,即栈内存可
以理解成线程的私有内存。
 堆内存中的对象对所有线程可见。堆内存中的对象可以被所有线程访问。
 空间大小
栈的内存要远远小于堆内存
栈溢出
参数:-Xss256k
java.lang.StackOverflowError 一般的方法调用是很难出现的,如果出现了要考虑是否有无限递归。
虚拟机栈带给我们的启示:方法的执行因为要打包成栈桢,所以天生要比实现同样功能的循环慢,所以树的遍历算
法中:递归和非递归(循环来实现)都有存在的意义。递归代码简洁,非递归代码复杂但是速度较快。
OutOfMemoryError:不断建立线程。(一般演示不出,演示出来机器也死了)

JVM第一节:内存结构相关推荐

  1. JVM学习-Java内存结构(详细易懂)

    Java内存结构 1.JVM概述 2.程序计数器 2.1.定义 2.2.作用及特点解释 3.虚拟机栈 3.1.栈的特点 3.2.栈的演示 3.3.栈的问题辨析 3.4.栈的线程安全问题 3.5.栈内存 ...

  2. [转]JVM运行时内存结构

    [转]http://www.cnblogs.com/dolphin0520/p/3783345.html 目录[-] 1.为什么会有年轻代 2.年轻代中的GC 3.一个对象的这一辈子 4.有关年轻代的 ...

  3. JVM运行时内存结构学习

    学习JVM运行模型比较重要,先看一幅图片: 运行时数据区(内存结构) :  1.方法区(Method Area) 类的所有字段和方法字节码,以及一些特殊方法如构造函数,接口代码也在这里定义.简单来说, ...

  4. JVM详解——内存结构

    如果有兴趣了解更多相关内容,欢迎来我的个人网站看看:耶瞳空间 一:JVM基本介绍 JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,具体实现有很 ...

  5. 英语语法第一节(句子结构)

    自己英语太差了,开个新坑,每天学完英语自己写一个博客复习一下. 先凭自己的记忆写一下所学的东西. 讲解结构:英汉语法的结构,三大基本结构,三大特殊结构 一.英汉语法的差异 我们不能凭空把脑子里的中文翻 ...

  6. Java 内存模型和 JVM 内存结构真不是一回事

    这两个概念估计有不少人会混淆,它们都可以说是 JVM 规范的一部分,但真不是一回事!它们描述和解决的是不同问题,简单来说, Java 内存模型,描述的是多线程允许的行为 JVM 内存结构,描述的是线程 ...

  7. 万万没想到,JVM内存结构的面试题可以问的这么难?

    在我的博客中,之前有很多文章介绍过JVM内存结构,相信很多看多我文章的朋友对这部分知识都有一定的了解了. 那么,请大家尝试着回答一下以下问题: 1.JVM管理的内存结构是怎样的?  2.不同的虚拟机在 ...

  8. 原创 | 万万没想到,JVM内存结构的面试题可以问的这么难?

    △Hollis, 一个对Coding有着独特追求的人△ 这是Hollis的第 223 篇原创分享 作者 l Hollis 来源 l Hollis(ID:hollischuang) 在我的博客中,之前有 ...

  9. JVM之深入理解JVM内存结构(Java内存结构/Java内存区域)、Java内存模型

    Java作为一种面向对象的,跨平台语言,其对象.内存等一直是比较难的知识点.而且很多概念的名称看起来又那么相似,很多人会傻傻分不清楚.比如本文我们要讨论的JVM内存结构.JAVA内存结构.JAVA内存 ...

  10. <JVM上篇:内存与垃圾回收篇>01-JVM与Java体系结构

    笔记来源:尚硅谷 JVM 全套教程,百万播放,全网巅峰(宋红康详解 java 虚拟机) 文章目录 1.JVM 与 Java 体系结构 1.1. 前言 1.2. 面向人群及参考书目 1.3. Java ...

最新文章

  1. 全球首次!中国黑客通过安全漏洞远程攻破特斯拉,可在行驶中“帮”你刹车...
  2. iOS消息推送机制原理与实现
  3. 二十八、Pyspider 爬取链家网
  4. npm安装和Vue运行
  5. MySQL-8.0.12源码安装实例
  6. Andorid之BINDSERVICE的使用方法总结
  7. NYOJ88(数论)
  8. react native windows create bundle folder
  9. 喝酒的规矩(是男人必看必顶,女人可不看直接顶)
  10. WinForm设置窗体默认控件焦点
  11. jmeter-正则表达式提取器
  12. 图解Kafka中的数据采集和统计机制
  13. 32位Linux系统时间截止,linux – 如果系统设置为2038年以后的日期,则ntpdate失败
  14. mac book pro osX10.8.5无法创建可引导的usb驱动器格式化失败解决方案
  15. 如何做好电商平台的内容运营?
  16. ubuntu16.04中 vim8 backspace键删除功能失效
  17. re正则表达式匹配多行文本
  18. 怎么做硬件产品的需求分析?
  19. apache-ab 并发负载压力测试
  20. 022kuo_zhan_guan_li_qi

热门文章

  1. JDBC08时间处理
  2. 简单说几个常见的数据结构
  3. hp ux安装oracle 11g,HP UX安装oracle 11g asm扫不到盘
  4. 【servlet】搭建servlet环境
  5. javaweb环境的配置 以及tomcat的安装
  6. mysql操作--json/数组 的增删该查
  7. spring boot 相关快捷内置类和配置
  8. Centos7 FastDFS 安装和配置启动
  9. Lintcode203 Segment Tree Modify solution 题解
  10. git使用笔记(二)分支与合并