博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
jvm运行机制
阅读量:4185 次
发布时间:2019-05-26

本文共 1904 字,大约阅读时间需要 6 分钟。

文章目录

jvm启动流程

1、java或者javaw命令启动。

2、系统装载配置,根据当前路径和系统版本寻找jvm.cfg(jvm的配置文件)。
3、根据配置找到JVM.dll,jvm.dll为jvm的主要实现。
4、初始化JVM获得JNIEnv接口,JNIEnv为JVM接口,findClass等操作通过它实现。
5、找到main方法并运行。
在这里插入图片描述

jvm基本结构

在这里插入图片描述

一、PC寄存器

  1. 每个线程拥有一个PC寄存器。
  2. 在线程创建时创建
  3. 指向下一条指令的地址
  4. 执行本地方法时,PC的值为undefind。

二、方法区

  1. 保存装载的类信息
    – 类型的常量池
    – 字段,方法信息
    – 方法字节码
    (JDK6时,String等常量信息置于方法区;JDK7时,已经移动到了堆。)
  2. 通常和永久区(Perm)关联在一起,永久区保存相对于静止和相对稳定的数据。

三、Java堆

  1. 和程序开发密切相关
  2. 应用系统对象都保存在Java堆中
  3. 所有线程共享Java堆
  4. 对分代GC来说,堆也是分代的
  5. GC的主要工作区
    在这里插入图片描述

四、Java栈(先进后出的数据结构)

  1. 线程私有的。
  2. 栈由一系列帧组成(因此Java栈也叫做帧栈)。
  3. 帧保存一个方法的局部变量、操作数栈、常量池指针。
  4. 每一次方法调用创建一个镇,并压栈。
  5. 局部变量表包含参数和局部变量,局部变量表中由很多槽位组成,每个槽位为32位。
    示例:如果为static方法,第一个槽位是就是第一个参数。如果不是static方法,第一个槽位为这个对象本身this。
    在这里插入图片描述
  6. 函数调用组成帧栈
    示例:在下面这个递归方法调用时,每调用一次产生一个帧。
    在这里插入图片描述
  7. 操作数栈
    Java没有寄存器,所有参数传递使用操作数栈。
    示例:a是局部变量0,b是局部变量1,c是局部变量2。压栈是将数据添加到操作数栈中去。
    在这里插入图片描述
  8. 栈上分配
    在一个方法中使用new创建对象,用完之后需要将对象delete掉,如果不这样做就很有可能发生内存溢出,如果在方法中只声明一个对象的引用,这样引用只会保存在栈中,随着方法的运行结束,自动清理。
    分配的时候很大的时候,jvm会做一些优化。
    在这里插入图片描述
    (1)栈上分配一般只能分配小对象(一般几十个bytes),在没有逃逸的情况下,可以直接分配在栈上。(逃逸是指如果这个对象除了在这个线程要用,在其他线程也要用,就不可以分配在栈上。因为栈的线程是私有的。
    (2)栈上分配–直接分配在栈上,可以自动回收,减轻GC的压力。
    (3)大对象或者逃逸对象无法栈上分配。

五、栈、堆、方法去交互

在这里插入图片描述

内存模型

  • 每一个线程有一个工作内存和主内存独立。
  • 工作内存中存放主内存中变量值的拷贝。
    在这里插入图片描述

1、当数据从主内存复制到工作内存存储时,必须出现两个动作:第一,由主内存执行的读(read)操作;第二,由工作内存执行相应的load操作。

2、当数据从工作内存拷贝到主内存时,也出现两个操作:第一个,由工作内存指定相应的存储(store)操作;第二,由主内存执行相应的写(write)操作。

3、每一个操作都是原子的,即执行期间不会被中断。

4、对于普通变量,一个线程中更新的值,不会马上反应在其他变量中。如果需要在其他线程中立即可见,需要使用volatile关键字。

在这里插入图片描述
5、可见性:一个线程修改了变量,其他线程可以立即知道。
6、保证可见性的方法:

  • volatile关键字
  • synchronized(unlock之前,写变量值回主存)
  • final(一旦初始化完成,其他线程就可见)
    7、有序性
  • 在本线程内,操作都是有序的。
  • 在线程外(多个线程)观察,操作都是无序的。(指令重排或主内存同步延时)
    8、指令重排
  • 线程内串行语义
    在这里插入图片描述
    线程A先执行writer()方法,a=1和flag=true执行的顺序可能打乱,不管谁先执行,在本线程内看来都是有序的。在线程B看来,a=1和falg=true的执行顺序就是无序的。

在这里插入图片描述

在这里插入图片描述
9、指令重排的基本原则

  • 程序顺序原则:一个线程内保证语义的串行性。
  • volatile规则,volatile变量的写,先发生于读。
  • 锁规则:解锁(unlock)必然发生在随后的加锁(lock)前
  • 传递性:A先于B,B先于C,那么A必然先于C
  • 线程的start方法先于它的每一个动作
  • 线程的所有操作先于线程的终结(Thread.join())
  • 线程的中断(interrupt())先于被中断线程的代码
  • 对象的构造函数执行结束先于finalize()方法。

编译和解释运行的概念

1、解释执行

  • 解释执行以解释方式运行字节码
  • 解释执行的意思是:第一句执行一句
    2、编译运行(JIT)
  • 将字节码编译成机器码
  • 直接执行机器码
  • 运行时编译
  • 编译后性能有数量级的提升

转载地址:http://pnfoi.baihongyu.com/

你可能感兴趣的文章
Collections的随机排序
查看>>
Java遍历Map的四种方法及对比
查看>>
libsvm的经典总结(全面至极)
查看>>
身份证合法性校验
查看>>
System.getProperties(); //系统属性
查看>>
java读取clob字段的方法
查看>>
java的实现图片合并
查看>>
GP数据库参数配置
查看>>
GP数据库参数配置
查看>>
MySQL实现了四种通信协议
查看>>
Lucene基本API组件
查看>>
什么是AI,叫人工智能,和BI,商业智能有什么区别
查看>>
根域名服务器
查看>>
Java基础 字符、字符串
查看>>
堆,栈,队列,串
查看>>
Java集合框架List,Map,Set等全面介绍
查看>>
流式大数据处理的三种框架:Storm,Spark和Samza
查看>>
Cypher查询语言--Neo4j中的SQL
查看>>
ha----双机集群(HA)系统简称
查看>>
Linux 高可用(HA)集群之keepalived详解
查看>>