JVM基础知识以及优化

JVM

概念

java Virtual machine ----java虚拟机:java程序的运行时环境
每一层都是包含关系,JVM是最低层与操作系统交互的二进制代码的运行时环境

区分java内存结构与java内存模型(JMM)

常见的JVM

JVM其实是一套规范,开发JVM需要准守这个规范
常见的开发JVM的实例有:oracle公司的hotspot
在这里插入图片描述

结构

编译后的二进制文件----需要进行类加载器进行加载到JVM中----类需要放在内存结构的方法区中----创建的对象放在堆中----调用方法时需要用到虚拟机栈、程序计数器、本地方法栈------方法执行时是由执行引擎中的解释器每一行进行执行,其中热点的代码可以进行放在即时编译器。有一些java代码 不好实现的功能,需要使用本地方法接口调用操作系统的本地方法接口进行实现
JVM组成部分:类加载器、JVM内存、执行引擎

JVM内存结构

1程序计数器(寄存器)

在这里插入图片描述

1.java源代码------>编译后二进制的字节码(JVM指令(对所有平台是一致的))---->通过java虚拟机中的组件:解释器处理成为机器码------>这样机器码就能被cpu执行
2.与此同时,解释器是从程序计数器中读取指令的内存地址的(即程序计数器来记住下一条指令的内存地址),然后解释器从二进制字节码中找到对应的jvm指令

3.特点:
线程是私有的(java程序支持多线程运行,cpu的调度器组件给每个线程分配时间片,然后交替的执行每个线程,每个线程都有自己的独属于的程序计数器)
程序计数器不会存在内存溢出问题

2虚拟机栈

每个线程在运行时需要内存空间来存储,这个 内存空间叫做虚拟机栈
在这里插入图片描述
垃圾回收只是对堆内存进行垃圾回收,不会对虚拟机栈进行垃圾回收

虚拟机栈内存溢出

1.什么情况导致栈内存溢出 java.lang.stackoverflowerror
栈帧过多超过了栈内存(例如方法的递归调用,但未设置合理的或者没有结束条件)
栈帧过大超出栈内存

虚拟机栈与线程有关,线程运行诊断

cpu占用过高:
1.

[root]# top

利用top命令查看所有的进程

[root]# ps  H  -co pid,tid,%cpu | grep  32655

ps H 命令来诊断所有运行的线程的占用cpu情况
-co 可以指定只关注几列(进程id,线程id,cpu占用情况)
| grep 进程id 来进行筛选出所有该进程下的线程
2.
jdk提供的命令:

jstack 32655

查看该进程id 的所有的线程

线程执行没有结果(有可能产生了死锁):

jstack 32655
3本地方法栈

JVM在调用本地方法时候,需要给本地方法提供内存空间,不是由java代码编写的方法的叫做本地方法,与底层操作系统来调用功能

4堆

通过new进行创建对象,需要使用堆内存
线程共享,需要考虑线程安安全的问题

堆内存溢出

该对象一直在使用无法进行垃圾回收内存,则会产生内存溢出

堆内存诊断

在这里插入图片描述
进行垃圾回收之后,堆内存占用还是很高,如何排查?
利用jconsole进行执行GC垃圾回收,Jmap进行查看新生代和旧生代的占用

**`jvisualvm`   命令可视化的方法展现jvm**  

使用里面的堆dump -----生成当前堆内存的快照----查看其中的对象占用内存情况
在这里插入图片描述

GC垃圾回收机制
判断对象是否回收

1.引用计数法
对象被引用的次数加一或者不再引用则减一,弊端循环引用
2.可达性分析算法(java虚拟机使用的方法)
①首先对所有的对象进行扫描
②如果是被根对象进行引用的对象(即沿着GC root对象为起点的引用链能够找到该对象),那么不能当成垃圾,反之即可
根对象(GC Root):肯定不能当做垃圾的对象叫做根对象
如何分析是不是根对象?利用java提供的工具 MAT(分析快照)、JMAP(产生快照)
在这里插入图片描述
3.五种引用(强软弱、虚引用、终结器引用)

垃圾回收算法

1.标记-清除(清除:就是将该内存地址的起始地址放到可分配的列表中,等待下次被分配占用,不需要清除里面的东西)
2.标记-整理(整理:避免内存碎片问题,会排序内存连续空间,对象需要移动)
3.复制(先标记空闲对象的内存,将没标记的转到 to 内存中,然后回收from里的,再交换from 与 to 的指向)
在这里插入图片描述

分代垃圾回收算法(java虚拟机中使用的,垃圾回收算法的协同工作)

在java虚拟机中不会单独使用一种垃圾回收算法,会多种算法共同应用工作,具体的实现就是虚拟机中的分代垃圾回收
在这里插入图片描述

垃圾回收器

分类:
1.串行
2.吞吐量优先
3.响应时间优先

举例:
CMS垃圾回收器
G1垃圾回收器:在这里插入图片描述

垃圾回收调优
5方法区

线程共享,需要考虑线程安安全的问题
方法区存储的信息,跟类的结构有关的信息:类的成员变量,成员方法和构造器方法的代码,类的构造器,运行时常量池
在jvm运行时开辟方法区内存
方法区在逻辑上是堆的组成一部分,但是在实际的厂商在创建jvm时,不一定都是属于堆的一部分的,也有使用操作系统的本地内存的。例如在oracle厂商中hotspot虚拟机在1.6版本是利用 永久代 进行实现的

在这里插入图片描述

方法区内存溢出

1.元空间(1.8版本 之后的名称)的小,但是类加载器创建的类的二进制字节码比较多,那就造成内存溢出

运行时常量池

二进制字节码文件(类基本信息,常量池,类方法定义,包含了虚拟机指令)
将class文件反编译 javap -v xxx.class
常量池:就是常量表,虚拟机的jvm指令可以根据这张表进行找到要执行的;类名,方法名,参数类型,字面量等信息
运行时常量池:常量池就是在class文件中的一个表,当这个类被加载到虚拟机中,他的常量池信息需要放在内存中,也就是运行时常量池,把前面的 #xx 对应表序号转化成真正的内存地址。
在这里插入图片描述

stringtable(串池)

在这里插入图片描述

直接内存(属于系统内存,不是jvm内存空间)

buffer在系统内存创建一个directmemory缓冲区

类加载与类的字节码结构

java源文件通过编译器进行编译成类文件
类文件:就是java字节码文件(包含字节码指令)
字节码文件通过类加载器进行类加载(其中有很多的阶段),然后加载到虚拟机中就可以执行其中的字节码指令了
执行的时候需要执行引擎的解释器进行解释执行,但是在解释的过程中会对其中的热点代码进行运行期的编译处理

类文件结构

字节码文件通过类加载器进行类加载(其中有很多的阶段),然后加载到虚拟机中就可以执行其中的字节码指令了
执行的时候需要执行引擎的解释器进行解释执行,但是在解释的过程中会对其中的热点代码进行运行期的编译处理

类文件

java源文件通过编译器进行编译成类文件
类文件:就是java字节码文件(包含字节码指令)

结构

类文件的结构是根据JVM的规范来的,各个虚拟机开发厂商在实现虚拟机的时候需要准守这个结构规范:
在这里插入图片描述
1.魔数
四个字节,所有文件都是一个自己的特定类型
四个字节来表示自己是class文件,而不是其他文件
ca fe ba be
2.版本
四个字节,表示类的版本20202034 中的34表示java 8

字节码指令
javac -parameters -d . Helloworld.java

编译java源文件,然后npp的二进制查看插件:
在这里插入图片描述
如果自己进行分析类文件结构过于麻烦,使用提供的javap 反编译class文件:

javap -v HelloWorld.class

在这里插入图片描述
文件的自己信息(修改时间,md5,编译来源)
全类名
版本信息
修饰符级别
常量池
方法信息(构造方法,本地变量,main方法,局部变量)

图解运行流程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

编译期处理

java编译器 将 .java源代码文件 进行编译为 .class文件的过程叫做 编译期
在这里插入图片描述

类加载阶段

类加载阶段可以分为三个阶段:加载、链接、初始化

加载阶段(与链接交替执行)

class文件要运行的话,需要类加载器进行将文件(字节码文件)加载到jvm的方法区中。内部采用c++ 的 instanceKlass 数据结构来描述java类

链接阶段(与加载交替执行)

链接可以分为三个步骤:验证、准备 、解析

验证步骤:

在这里插入图片描述
比如修改了class字节码的格式等等一些信息的话,在链接的过程中验证不能通过

准备步骤:

在这里插入图片描述

解析步骤:

HSDB工具监控连接的进程id:

java -cp ./lib/sa-jdi.jar sun.jvm.hotspot.HSDB

在这里插入图片描述

初始化阶段

就是执行类的初始化方法,()v方法
在这里插入图片描述
在这里插入图片描述

类加载器

(类加载中有层级关系):

在这里插入图片描述

运行期优化
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风吹海洋浪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值