代码编织梦想

学习JVM(一)

一、java字节码技术

1.什么是字节码

Java bytecode 由单字节(byte)的指令组成,理论上最多支持 256 个操作码(opcode)。 实际上 Java 只使用了200左右的操作码, 还有一些操作码则保留给调试操作。Java的字节码技术,就是java程序具有可移植性和适应所有操作系统的根本原因。因为不管是什么样的操作系统最后计算机解析的都是java的字节码,所以不会受到影响。
根据指令的性质,主要分为四个大类:

  1. 栈操作指令,包括与局部变量交互的指令 2. 程序流程控制指令
  2. 对象操作指令,包括方法调用指令
  3. 算术运算以及类型转换指令

2.生成字节码

在这里插入图片描述
编译:javac demo/jvm0104/HelloByteCode.java
查看字节码:javap -c demo.jvm0104.HelloByteCode

结果如下:

在这里插入图片描述

3.字节码的运行时结构

JVM 是一台基于栈的计算机器。 每个线程都有一个独属于自己的线程栈(JVM Stack),用于存储栈帧(Frame)。每一次方法调用,JVM 都会自动创建一个栈帧。 栈帧由操作数栈, 局部变量数组以及一个 Class 引用组成。 Class 引用 指向当前方法在运行时常量池中对应的 Class。

这是一个动态的例子,按照字节码顺序 常量1进入局部变量区0,常量2进入局部变量区1, 然后加载0,1进入栈进行相加操作 然后与常量5进行相乘,值进入局部变量区2,结束返回。
在这里插入图片描述

二、 jvm的类加载器

1.类的生命周期

在这里插入图片描述
类的加载周期分为七步,加载过程分为五个步骤。在加载一个类

  1. 加载(Loading):找 Class 文件
  2. 验证(Verification):验证格式、依赖
  3. 准备(Preparation):静态字段、方法表
  4. 解析(Resolution):符号解析为引用
  5. 初始化(Initialization):构造器、静态变 量赋值、静态代码块
  6. 使用(Using)
  7. 卸载(Unloading)

2.类的加载时期

  1. 当虚拟机启动时,初始化用户指定的主类,就是启动执行的 main 方法所在的类;
  2. 当遇到用以新建目标类实例的 new 指令时,初始化 new 指令的目标类,就是 new 一个类的时候要初始化;
  3. 当遇到调用静态方法的指令时,初始化该静态方法所在的类;
  4. 当遇到访问静态字段的指令时,初始化该静态字段所在的类;
  5. 子类的初始化会触发父类的初始化;
  6. 如果一个接口定义了 default 方法,那么直接实现或者间接实现该接口的类的初始化, 会触发该接口的初始化;
  7. 使用反射 API 对某个类进行反射调用时,初始化这个类,其实跟前面一样,反射调用 要么是已经有实例了,要么是静态方法,都需要初始化;
  8. 当初次调用 MethodHandle 实例时,初始化该 MethodHandle 指向的方法所在的类。

3.类加载器

java的类加载器使用的双亲委派机制,即先有父类加载器进行加载,父类无法加载再由自己加载。这样的机制是为了避免类的重复加载。
在这里插入图片描述
三类加载器:

  1. 启动类加载器(BootstrapClassLoader) 加载根目录下的jar
  2. 扩展类加载器(ExtClassLoader) 在exc目录下的jar包
  3. 应用类加载器(AppClassLoader)

三、jvm的内存模型

1.jvm内存结构

1.每个线程都只能访问自己的线程栈。
2.每个线程都不能访问(看不见)其他线程的局部变量。
3.所有原生类型的局部变量都存储在线程栈中,因此对其他线程是不可见的。
4.线程可以将一个原生变量值的副本传给另一个线程,但不能共享原生局部变量本身。
5.堆内存中包含了 Java 代码中创建的所有对象,不管是哪个线程创建的。 其中也涵盖了包装类型 (例如 Byte,Integer,Long 等)。
6.不管是创建一个对象并将其赋值给局部变量, 还是赋值给另一个对象的成员变量, 创建的对象都 会被保存到堆内存中。

2.jvm的整体结构

1.jvm内存的整体结构

在这里插入图片描述
1.每启动一个线程,JVM 就会在栈空间栈分 配对应的 线程栈, 比如 1MB 的空间(- Xss1m)。
2.线程栈也叫做 Java 方法栈。 如果使用了 JNI 方法,则会分配一个单独的本地方法栈 (Native Stack)。
3.线程执行过程中,一般会有多个方法组成调 用栈(Stack Trace), 比如 A 调用 B,B 调用 C。。。每执行到一个方法,就会创建对应的栈帧(Frame)。

2.jvm栈内存结构

在这里插入图片描述
栈帧是一个逻辑上的概念,具体的大小在一个方法编写完成后基本上就能确定。比如返回值 需要有一个空间存放吧,每个 局部变量都需要对应的地址空间,此外还 有给指令使用的 操作数栈,以及 class 指 针(标识这个栈帧对应的是哪个类的方法, 指向非堆里面的 Class 对象)。

3,jvm的堆内存结构

在这里插入图片描述
堆内存是所有线程共用的内存空间,JVM 将Heap 内存分为年轻代(Young generation)和 老年代(Old generation, 也叫 Tenured)两部分。
一、年轻代还划分为 3 个内存池,新生代(Eden space)和存活区(Survivor space), 在大部分 GC 算法中有 2 个存活区(S0, S1),在我们可 以观察到的任何时刻,S0 和 S1 总有一个是空的, 但一般较小,也不浪费多少空间。Non-Heap 本质上还是 Heap,只是一般不归 GC 管理,里面划分为 3 个内存池。
二、Metaspace, 以前叫持久代(永久代, Permanent generation), Java8 换了个名字叫 Metaspace.CCS, Compressed Class Space, 存放 class 信 息的,和 Metaspace 有交叉。Code Cache, 存放 JIT 编译器编译后的本地机器 代码。

四、jvm的启动参数

在这里插入图片描述
以-开头为标准参数,所有的 JVM 都要实现这些参 数,并且向后兼容。

-D 设置系统属性。

以 -X 开头为非标准参数, 基本都是传给 JVM 的, 默认 JVM 实现这些参数的功能,但是并不保证所 有 JVM 实现都满足,且不保证向后兼容。 可以使 用 java -X 命令来查看当前 JVM 支持的非标准参 数。

以 –XX:开头为非稳定参数, 专门用于控制 JVM 的行为,跟具体的 JVM 实现有关,随时可能会在 下个版本取消。
-XX:±Flags 形式, ± 是对布尔值进行开关。 -XX:key=value 形式, 指定某个选项的值。

1.jvm启动参数–堆内存

1.Xmx, 指定最大堆内存。 如 -Xmx4g. 这只是限制了 Heap 部分的最大值为4g。这个内存不包括栈内存,也不包括堆外使用的内存。

2.-Xms, 指定堆内存空间的初始大小。 如 -Xms4g。 而且指定的内存大小,并 不是操作系统实际分配的初始值,而是GC先规划好,用到才分配。 专用服务 器上需要保持 –Xms 和 –Xmx 一致,否则应用刚启动可能就有好几个 FullGC。 当两者配置不一致时,堆内存扩容可能会导致性能抖动。

3.-Xmn, 等价于 -XX:NewSize,使用 G1 垃圾收集器 不应该 设置该选项,在其 他的某些业务场景下可以设置。官方建议设置为 -Xmx 的 1/2 ~ 1/4.

4.-XX:MaxPermSize=size, 这是 JDK1.7 之前使用的。Java8 默认允许的 Meta空间无限大,此参数无效。

5.-XX:MaxMetaspaceSize=size, Java8 默认不限制 Meta 空间, 一般不允许设 置该选项。

6.-XX:MaxDirectMemorySize=size,系统可以使用的最大堆外内存,这个参 数跟 -Dsun.nio.MaxDirectMemorySize 效果相同。

7.-Xss, 设置每个线程栈的字节数。 例如 -Xss1m 指定线程栈为 1MB,与- XX:ThreadStackSize=1m 等价

2.jvm启动参数–GC相关

1.-XX:+UseG1GC:使用 G1 垃圾回收器

2.-XX:+UseConcMarkSweepGC:使用 CMS 垃圾回收器

3 -XX:+UseSerialGC:使用串行垃圾回收器

  1. -XX:+UseParallelGC:使用并行垃圾回收器

3.jvm启动参数–分析诊断

1.-XX:±HeapDumpOnOutOfMemoryError 选项, 当 OutOfMemoryError 产生,即内存溢出(堆内存或持久代)时,自动 Dump 堆内存。
示例用法: java -XX:+HeapDumpOnOutOfMemoryError -Xmx256m ConsumeHeap

2.-XX:HeapDumpPath 选项, 与 HeapDumpOnOutOfMemoryError 搭配使用, 指定内存溢出时 Dump 文件的目录。如果没有指定则默认为启动 Java 程序的工作目录。
示例用法: java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/usr/local/ ConsumeHeap
自动 Dump 的 hprof 文件会存储到 /usr/local/ 目录下。

3.-XX:OnError 选项, 发生致命错误时(fatal error)执行的脚本。
例如, 写一个脚本来记录出错时间, 执行一些命令, 或者 curl 一下某个在线报警的 url. 示例用法:java -XX:OnError=“gdb - %p” MyApp
可以发现有一个 %p 的格式化字符串,表示进程 PID。

4.-XX:OnOutOfMemoryError 选项, 抛出 OutOfMemoryError 错误时执行的脚本。 -XX:ErrorFile=filename 选项, 致命错误的日志文件名,绝对路径或者相对路径。 -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=1506,远程调试

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_45640004/article/details/128019151

jvm学习目录-爱代码爱编程

本页为jvm学习系列的目录。 上次更新 2020.05.29 陆续更新中 最近有些忙,可能会更新python,ksvd这些文章,JVM系列的要鸽一鸽了 java内存区域 jvm学习 java内存区域jvm学习 java字符串常量池以及String常见简单面试问题 垃圾回收 jvm学习 谁是垃圾?判断对象是否能被垃圾回收 可达性分析 四大引用jvm

JVM学习1_ javac编译器源码编译及分析-爱代码爱编程

         javac编译器是纯java代码编写的,用来把*.java文件编译成二进制*.class文件 一、获取javac编译器源码         github下载jdk源码,jdk源码中包含javac编译器源码、hotspot虚拟机等 下载地址https://github.com/openjdk/jdk 二、新建openjdk_java

JVM学习笔记(一:JVM概述)-爱代码爱编程

JVM学习笔记:一:JVM概述 JVM概述JVM的作用JVM 特点JVM的位置JVM的组成Java代码的执行流程JVM 架构模型 虚拟机:Virtual Machine ,是一款软件,用来执行一系列计算机指令。大体上,虚拟机可以分为系统虚拟机和程序虚拟机。VMware属于系统虚拟机,是对物理计算机的仿真,提供了一个可运行完整操作系统的平台

jvm学习-爱代码爱编程

一,初识jvm jvm java virtual machine 顾名思义java虚拟机。 用于执行jvm规范的代码的。也是java跨平台的实现支撑。 二,jvm知识体系 内存结构是jvm核心内容。其他,垃圾回收,性能调优,JVM自身优化技术,执行引擎, 监控工具,类文件结构,类加载。都需要围绕内存结构。   二.一内存模型。

【java】jvm学习_多糖橘橘子的博客-爱代码爱编程

目录 Java虚拟机: JVM位置: JVM架构:(要能画出来) JVM 生命周期: 类加载器: Java虚拟机: 1、Java虚拟机是一台执行Java字节码的虚拟计算机,它拥有独立的运行机制,其运行的Java字节码也未必由Java语言编译而成。 2、JVM平台的各种语言可以共享Java虚拟机带来的跨平台性、优秀的垃圾回收器,以及可

javase从基础到入门:抽象类和接口_monody·的博客-爱代码爱编程

1.抽象类 1.抽象类的概念 在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。 比如: 在打