JVM

1. java运行过程

看一段示例代码:

public class ADD {

    private int add(int a, int b) {
        return a+b;
    }

    public static void main(String[] args) {
        ADD add = new ADD();
        System.out.println(add.add(1, 2));
    }

}

运行结果也很简单,打印3

那么他是怎么运行的呢?

从表面看就是javac ADD.java然后生成了ADD.class文件,然后java ADD.class就运行了。

它的实际上也很好理解

6262743-1f8c2df55e8ecdbf.png
  1. 首先把java文件编译成class文件
  2. 然后通过类加载子系统把class文件加载到运行时数据区(内存)里面去,这个内存空间呢又有不同的分区,一个class文件里面的东西以及这个class运行的过程中需要用到的内存,都会被安排在不同的地方。所以这个运行时数据区还有细分,稍后详细介绍这些细分。
  3. jvm的执行引擎去执行这个class文件。这样就让代码跑起来了。执行引擎就是把class文件翻译成对应的系统操作可以执行的1010101。

2. 运行时数据区

6262743-a7cf356eadd047ce.png
jvm体系
6262743-9bd8c77593d56d72.png
运行时数据区

2.1 方法区

存放:静态变量(1.7以后放在了堆里面)+常量+类信息+运行时常量

啥是静态变量?-----static定义的量
啥是常量?------final定义的量
啥是类信息?------类的方法,方法的名字,方法的返回值,方法的访问权限,类包含的变量常量都是类信息。
运行时常量?-----用于存放编译期生成的字面量和符号引用。

JDK 1.8 中,已经没有方法区(因为没有了永久代,方法区物理上存在于堆里,而且是在堆的持久代里面;但在逻辑上,方法区和堆是独立的。而且一般说堆的持久代就是说方法区),而是将方法区直接放在一个与堆不相连的本地内存区域(Native Memory),这个区域被叫做元空间。

2.2 java 栈

2.2.1 java 栈

java线程执行方法的内存模型,一个线程对应一个栈,每个方法在执行的同时都会创建一个栈帧(用于存储局部变量表,操作数栈,动态连接,方法出口等信息),java栈不存在垃圾回收问题,只要线程一结束该栈就会释放,生命周期和线程一致。

java 栈是线程私有,存放的是一个个栈帧,可以理解为每一个栈帧代表一个方法。栈帧里面具体存放的东西稍后再看。

还是看之前的代码:

public class ADD {

    private int add(int a, int b) {
        return a+b;
    }

    public static void main(String[] args) {
        ADD add = new ADD();
        System.out.println(add.add(1, 2));
    }

}

这段代码是在主线程中执行的,首先执行main方法,然后执行ADD的add方法,然后add执行完继续执行main方法。那么在java栈中的过程是这样的:


6262743-04ae78e08a99b5d7.png
java栈执行变化过程

就很好理解,为什么java栈是线程私有的,而且不存在垃圾回收问题,为什么它和线程的生命周期是一致的。

2.2.2 栈帧的内容

栈帧包含局部变量表,操作数栈,动态连接,方法出口等信息,为了搞清楚这些是干啥的,我们结合一个栈帧方法的运行过程来了解。

现在有一个方法如下:

public int add(){
  int a = 1;
  int b = 2;
  int c = (a+b)*10;
  return c;
}

运行过程如下:

  1. int a = 1;

把常量1压入操作数栈

6262743-3894500b18cd6f0f.png
常量1压入操作数栈

把常量1存入局部变量表(把1从操作数栈出栈,然后存到局部变量表)

6262743-625acb95e26541e2.png
常量1存入局部变量表
  1. int b = 2;

把常量2压入操作数栈

6262743-793cba6c216171e8.png
常量2压入操作数栈

把常量2存入局部变量表(把2从操作数栈出栈,然后存到局部变量表)

6262743-827626ebd99e8e36.png
常量2存入局部变量表
  1. c =(a+b)*10
    从局部变量表中加载变量的值入操作数栈,从操作数栈弹出两个变量的值进行加运算,运算结束将结果3压入操作数栈,将常量10压入操作数栈,将3和10弹出进行乘法运算,将结果30压入操作数栈,把常量30存入局部变量表。
6262743-0acb0c7596a0536e.png
把两个变量的值压入操作数栈
6262743-443f578d3fa426ed.png
从操作数栈弹出两个变量的值运算
6262743-c5842c67d9abe3aa.png
将结果3压入操作数栈
6262743-73e8535354875461.png
将常量10压入操作数栈
6262743-3257f88144dea97a.png
将3和10弹出进行乘法运算
6262743-29335b1d985cff46.png
将结果30压入操作数栈
6262743-d2bceeb58dc9d2bd.png
30出操作数栈,存入局部变量表

通过上面的过程应该已经理解了局部变量和操作数栈是什么了

方法出口的意思就是当前栈帧走完了以后会被移除出java栈,通过方法出口继续执行其他栈帧。

6262743-b008b58077dbc7e5.png
方法出口

2.3 程序计数器

程序计数器也是线程私有,作用是记录线程执行到哪个地方。

线程是要抢占cpu来执行的,那比如一次抢到了cpu,执行到了20的位置(这个位置不代表行数,应该是程序被cpu执行的最小单位),就用程序计数器记录,下次再抢到cpu的时候继续从20开始执行。

2.4 本地方法栈

那些用c编写的,用native修饰的方法

6262743-e7f602b39a3124eb.png

2.5 堆(线程共享)

虚拟机启动时创建,用于存放对象实例,几乎所有的对象都在堆上分匹配内存,当堆不够用的时候就会oom,堆是垃圾收集器管理的主要区域。可以通过-Xms -Xmx参数指定最小堆和最大堆。

像int a =1,这样的值就直接存在局部变量表里面,但是对于引用的话就存放在堆里面,而局部变量表里面的a只是一个地址,指向堆的位置。

6262743-3104b22647d660d6.png

3 堆

3.1 方法区和堆的永久代的关系,元空间和永久代的关系

通常说的方法区其实就是指代堆的永久区,那么为什么上面的jvm的图会把方法区和堆区分开呢?而不是将方法区画在堆的里面呢?因为永久代和堆在物理内存上面是不属于堆的,而在逻辑上新生代,老年代,永久代又递进关系,所以通常说堆的结构的时候会带上永久代。
那么方法区==永久区吗?
方法区是一个逻辑的概念,而永久代可以看作是方法区的具体实现,是实实在在存在的东西。

1.8以后取消永久代,采用元空间。元空间使用的是直接物理内存,跟堆完全隔离。

3.2 堆结构

之前已经介绍了堆是干啥的,下面看堆的结构

6262743-9f39f4408b72ebd0.png
堆的结构

3.2.1 新生代&Minor GC

6262743-af70169967a841a8.png
image.png

新生代占据1/3的堆空间,包含Eden,from,to三个部分,所占比例大概是8:1:1.

新生代的流程如下:

  • 新来的对象会先存在于eden区
  • eden满了,触发小gc,清理eden(至于怎么清理,涉及到垃圾清理算法,上面有介绍),将存活下来的放到from。
  • eden又慢了,触发小gc,清理eden和from,将存活下来的放到to。清空from,from在逻辑上变成to,to在逻辑上变成from。结果就是表现出来的始终是to是空的,from是存放的存活下来的,所以上图from和to之间是双箭头而不是单箭头
  • 如此反复,当经过15次(可配置)gc后依然活下去的就会被放到老年代。

3.2.2 老年代&Full GC

老年代也不能只进不出啊,老年代也会满,触发full gc。

full gc 程序会停止运行来进行垃圾回收,full gc比Minor GC耗时更多。

所谓的调优,也就是让full gc少执行,让Minor gc也少出现

3.2.3 垃圾回收算法

PS:内存碎片怎么产生的

6262743-6f492021627c280f.png
内存碎片
  • 引用计数
    当对象有一个引用时,增加一个计数,删除一个引用时,减少一个计数。垃圾回收时,只回收引用为0的对象。此算法无法处理循环引用的问题。(循环引用:A,B两个对象相互引用,这两个对象永远都不会销毁)

  • 复制
    把内存空间划分为两个相等的区域,每次只使用其中一个区域,垃圾回收时,遍历使用的区域,回收空间还可以整理碎片。


    6262743-2ebce96cb84ab6d6.png
    红色表示未使用的区域,灰色表示需要被回收的对象所占的区域,白色表示空闲区域,其他颜色表示不需要被回收的对象所占的区域
  • 标记-清除
    分为两个阶段,第一阶段标记所有被引用的对象,第二阶段遍历整个堆,把未标记的对象清除。此算法会暂停整个应用,并且会产生内存碎片。


    6262743-d5143ffd5985ef20.png
  • 标记-整理
    结合’标记-清除‘和’复制‘的优点,分为两个阶段。第一阶段标记所有被引用的对象,第二阶段遍历整个堆,把未标记的对象清除,并且存活的对象压缩到堆的其中一块,按顺序排放。此算法不需要两倍空间也不产生碎片。
6262743-47127058b7147c82.png

3.2.4 jvm垃圾收集器

scavenge GC(次收集)和full GC(全收集)

  • 次收集整理新生代,并且把存活的对象移动到Suivivor区,然后整理Suivivor的两个区。
  • 全收集整理老年代。

次收集:
新生代空间紧张时会被触发
收集频率比全收集多很多

全收集:
当老年代或者持久代空间满了触发
使用System.gc()触发
一般耗时比次收集长

3.2.5 分代垃圾收集器(不全,自查百度)

6262743-0ea7fc56503135cb.png

serial:串行收集器
parnew:并行收集器,是serial的多线程版本,单核下,不比serial优秀,在多核下才显示优势。
paralle scavenge:与parnew类似,也是使用复制算法,也是并行多线程收集器,更关注吞吐量。

等等

3.2.6 自带的工具

6262743-965bc299aa0dbe97.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值