性能优化专题(JVM性能优化)

什么是JVM

JDK : Java Development Kit : Java开发工具包,包含java编译器等一些开发工具.
JRE : Java Runtime Environment : Java运行时环境, 运行java程序的基础环境, 是jdk的子集
JVM : Java Virtural Machine: Java虚拟机, 程序在jvm中运行,可以通过java.exe程序开启一个jvm.
关于jdk的介绍:write once run everywhere
 我们的java文件被编辑生成与平台无关的.class文件在jvm上面运行
我们知道java是跨平台的可真的是跨平台的吗?
同一个jar包我们可以在windows(windows-version-jdk1.8)运行,也可以在linux(linux-version-jdk1.8)中运行。所以还是与平台有关,只不过要配置不同版本的jdk环境,就像玩了一个文字游戏似的。
同样也可以说C语言也是跨平台的,只不过相应编译器的库函数对CPU的指令集不同,所以相较而言只能说java是伪跨平台语言,还是和平台有关。

JVM的功能

软件层面的机器码翻译
回到java中来,.class文件要在机器上面运行,要转成机器识别的0101。所以jvm是在一个软层面进行了翻译,因为不同的操作系统底部的指令是不一样的。
内存管理
java的重中之重,经久不衰,企业首选就是jvm中有健壮内存管理功能,使我们能更专注的关注业务代码,不需要手动开启回收内存空间。
从辩证的角度来看,任何事情都有的两面性。
当我们出现内存泄漏和内存溢出的时候我们是一无所知的,因为我们把这些交给了jvm,所以我们要避免内存利用不当的出现,所以我们要学习jvm。

运行数据区

java代码在运行时的状态,即运行的时候的数据区。
计算机底部无非就是数据流、指令流、控制流。java中同样如此
在这里插入图片描述
jvm的运行时数据区为:数据区和指令区
在这里插入图片描述

指令区

程序计数器

程序计数器: 指向当前线程正在执行字节码指令地址或行号
类似CPU的时间切片,java运行的最小执行单位是线程,而线程是在cpu上面执行,而cpu的时间片是抢占式的,所以线程是可以被挂起的,比如同时看着电视聊着天有一种并行的感觉(单核CPU实则是并发的状态),实则是时间片在飞快的切换进行执行,当cpu要切换回来的时候,我要知道其地址才可以回到原来的地方继续执行。

虚拟机栈

虚拟机栈: 存储当前线程运行方法时所需要的数据、指令、返回地址。
(方法是由我们的线程来执行,线程只是一个执行体,执行方法需要数据i = 10 指令i+=10 返回地址 return )
其虚拟机栈就是一个栈的数据结构负责存储方法相关的数据信息,其单位为栈帧(一个方法一个栈帧)
在这里插入图片描述

这里着重介绍栈帧中局部变量表操作数栈动态链接出口

局部变量表

局部变量表[存储局部变量(形参或者方法内)]编译时确定大小,运行时有局部变量表**。局部变量表是定长的32位[int大小]寻址的位数,如果64位放两个slot。
在这里插入图片描述
关于局部变量表中引用类型的存储同样只能表示32位的地址
 局部变量中存储的是引用类型的声明,其引用指向了数据区的heap空间。

操作数栈

操作数栈[存储的是操作数]JAVAP指令集
举例:methodTwo(int num){int j = 3}将
0: iconst_3 int类型变量3压入栈,
1: istore_2将压栈的3的值弹栈存入局部变量2也就是j.在这里局部变量2是j,1是num,特性情况下0是this。
拓展:
iload_1:将局部变量表1的值load进操作数栈
iload_2:将局部变量表2的值load进操作数栈
iadd:将操作数栈中两个位置的值相加
istore_3:将其结果弹栈存入到局部变量表3

动态链接

动态链接(运行期间classLoader进jvm)
业务代码:
方法执行的时候才会去解析service相关。
方法执行process()的时候会去指向真正的实例,解析其Constant pool(常量池)去寻找。


常量其实叫做字面量(literals)其中还有符号引用(类和接口方法字段等的命名描述符)
d

出口

方法执行完之后需要出栈。
出栈或者方法结束之后可能会正常执行或者异常两种情况
正常即正常执行,异常要看其是try还是throws然后走相应的处理路线。


方法嵌套的时候后进的方法在栈顶
在这里插入图片描述
在这里插入图片描述
像其循环调用迭代,方法中就有n多栈帧,甚至有可能致其栈溢出

本地方法栈

和虚拟机栈类似的结构,其不同就是存储在本地,带native的就是本地方法,是c和c++实现的,源码在官网能看到。
本地方法

数据区

线程独享(绿色)和线程共享(非绿色)
在这里插入图片描述

方法区

类信息[类的描述文件可以理解为反编译后的内容]、常量(1.7+有变化)[1.7+之后将string的常量池移动到堆里面去了]、静态常量、JIT(just in time 即时编译 1.7以前)[动态代理生成的类信息classLoader进jvm]

内存模型(JMM)

对象生命周期不一样分代
三代:新生代(eden[8M],s0[1M],s1[1M])、老年代、永久代
jdk1.8之前是有永久代
1.8+的时候是取消了MetaSpace,不在堆里面是直接在内存里面分配的。
MetaSpace出现设计出来考虑的是
1.永久代会溢出的问题
2.像一个ArrayList可以自动扩容。
 虽然可以扩容,但不见得是好的。内存是固定的当扩容到把空间占满,堆内存就不够用了,所以要像堆内存一样定义好它的大小。


什么样的对象需要GC
判断算法

  • 引用计数法
  • 可达性分析
    引用计数法:相互引用,循环引用
    A里面引用了B,就在A里面记一个数。
    B里面引用A,同样记一个数。当记数等于0的时候就可以回收了。互相引用,循环依赖的时候jvm是不会回收的计数是1。
    可达性分析:GC Root中根据链接分析对象是否被引用,如果不被引用就回收,否则就不被回收
    在这里插入图片描述

哪些可以成为GC Roots

  • 虚拟机中本地变量表引用的对象
  • 方法区中
    • 类静态变量应用的对象
    • 常量引用的对象
  • 本地方法栈中JNI引用的对象

不可达是不是就一定被回收?
有没有必要执行在于是否实现finalize方法,可以在finalize中进行一次挽救。一个对象的finalize只能运行一次

  • finalize()

关于垃圾回收有时间再更

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值