JVM运行机制

一、JVM启动流程

203951_N4A1_3144678.png

二、JVM基本结构

204112_fYAj_3144678.png

    1、PC寄存器

        — 每个线程拥有一个PC寄存器

        — 在线程创建时 创建

        — 指向下一条指令的地址

        — 执行本地方法时,PC的值为undefined

    2、方法区

        — 存放类的原始信息,对类进行描述,包括常量和方法字节码

            特例:JDK6时,String等常量信息置于方法区 JDK7时,已经移动到了堆。

        — 保存装载的类信息

                > 类型的常量池

                > 字段,方法信息

                > 方法字节码

        — 通常和永久区(Perm)关联在一起(保存相对稳定的一些数据,变化很小,但热替换除外)

        注:方法区还是堆存放内容随着版本的变化而有所不同。

    3、Java堆

        — 和程序开发密切相关

        — 应用系统对象都保存在Java堆中

        — 所有线程共享Java堆

        — 对分代GC来说,堆也是分代的

        — GC的主要工作区间

204612_bMPl_3144678.png

复制算法

    4、Java栈

        — 线程私有

        — 栈由一系列帧组成(因此Java栈也叫做帧栈)

        — 帧保存一个方法的局部变量、操作数栈、常量池指针

        — 每一次方法调用创建一个帧,并压栈

        — Java栈 – 局部变量表 包含参数和局部变量

        — Java栈 – 函数调用组成帧栈

        — Java栈 – 操作数栈(因为jvm没有寄存器,相当于一个替代品)

        — Java栈 – 栈上分配(栈大小一般为几百k-1M)

            > 小对象(一般几十个bytes),在没有逃逸的情况下,可以直接分配在栈上

            > 直接分配在栈上,可以自动回收,减轻GC压力

            > 大对象或者逃逸对象无法栈上分配

            > 逃逸对象:一个栈上面分配的对象又被其它栈引用(这种情况是不可以的,因为栈是线程私有的)

            > 使用栈上分配的好处:当函数调用结束后,系统会自动回收栈(帧)所占用空间

        — 栈、堆、方法区交互

205111_HfPR_3144678.png

205156_CdD9_3144678.png

三、内存模型

    1、每一个线程有一个工作内存和主存独立

    2、工作内存存放主存中变量的值的拷贝

205327_wTSl_3144678.png

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

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

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

205447_0rlm_3144678.png

    6、volatile 不能代替锁, 一般认为volatile 比锁性能好(不绝对)。

    7、选择使用volatile的条件是: 语义是否满足应用。

四、相关概念

    1、可见性

        一个线程修改了变量,其他线程可以立即知道。

    2、保证可见性的方法

        — volatile

        — synchronized (unlock之前,写变量值回主存)

        — final(一旦初始化完成,其他线程就可见)

    3、有序性

        — 在本线程内,操作都是有序的

        — 在线程外观察,操作都是无序的。(指令重排 或 主内存同步延时)

    4、指令重排

         — 线程内串行语义

205851_dbT7_3144678.png

    5、指令重排 – 破坏线程间的有序性

205947_P8EO_3144678.png

    6、指令重排 – 保证有序性的方法

210034_xBTb_3144678.png

    7、指令重排的基本原则

        — 程序顺序原则:一个线程内保证语义的串行性

        — volatile规则:volatile变量的写,先发生于读

        — 锁规则:解锁(unlock)必然发生在随后的加锁(lock)前

        — 传递性:A先于B,B先于C 那么A必然先于C

        — 线程的start方法先于它的每一个动作

        — 线程的所有操作先于线程的终结(Thread.join())

        — 线程的中断(interrupt())先于被中断线程的代码

        — 对象的构造函数执行结束先于finalize()方法

五、编译和解释运行的概念

    1、解释运行

        — 解释执行以解释方式运行字节码

        — 解释执行的意思是:读一句执行一句

    2、编译运行(JIT)

        — 将字节码编译成机器码

        — 直接执行机器码

        — 运行时编译

        — 编译后性能有数量级的提升

    注:编译运行的运算速度至少快于解释运行数量级一倍以上。

转载于:https://my.oschina.net/Howard2016/blog/1592845

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值