jvm线程字节码指令执行示例

java线程工作内存在栈中吗_JVM学习笔记——java内存模型_大内义兴的博客-CSDN博客

概述

JVM规范希望定义一套java内存模型(java memory model,JMM),使得java程序在不同的硬件平台下面都能展现出一致的内存访问机制。

java内存模型规定所有变量保存在主内存中,每个线程有自己的工作内存。线程的工作内存中保存了该线程使用到的变量的主内存拷贝,线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存中的变量。不同的线程之间无法直接访问对方的工作内存,需通过主内存才能进行变量的传递。java内存模型围绕原子性、有序性、可见性三个方面展开。

d27ce5480ff7ad4c6be568282a6f2320.png

内存间交互操作

关于变量在工作内存和主内存之间的传递,java内存模型定义了以下8种原子操作:

lock:作用于主内存变量

unlock:作用于主内存变量

read:作用于主内存变量

load:作用于工作内存变量

use:作用工作内存变量

assign:作用于工作内存变量

store:作用于工作内存变量

write:作用于主内存变量

JVM保证了以上8种操作的原子性。这8种操作还有一些特殊的规则:

volatile变量保证了可见性与有序性,volatile变量的操作也需要遵循一些特殊的规则:

先行发生原则:

基于栈的指令

JVM指令是基于栈的指令架构,与之相对的是基于寄存器的指令,如x86平台。基于栈的指令集的优点是可移植,缺点是执行速度慢。

30967be787aac83000e45fd5b34db2ec.png

下面的基于栈的指令例子中,也有load、store等操作,这些属于工作内存中的操作,与内存之间的那8种原子操作不一样。

我们可以使用javap -c去获取java代码的字节码。字节码是运行在JVM上的指令。我们翻译一段简单的程序。看看基于栈的指令是如何工作的。

public int calc() {undefined

int a = 100;

int b = 200;

int c = 300;

return (a+b)*c;

}

public int calc();

Code:

0: bipush 100

2: istore_1

3: sipush 200

6: istore_2

7: sipush 300

10: istore_3

11: iload_1

12: iload_2

13: iadd

14: iload_3

15: imul

16: ireturn

51d941a1d0d5a6e54c07e9c2fcde59fd.png

d85e646b884a7504c2819f722bb36e79.png

fae381f683a5558970205aebf6d4819e.png

f751138340e9e5f16ab0fc8accb56f1a.png

74b7f2986c03df57e40af25fc053aebf.png

16f383a1f6073a9519bafc0c77bcedd2.png

e7747c7759b037eb467192dbb9125266.png

volatile的JVM指令

我试着去比较带volatile的程序和不带volatile的程序,javap之后显示,它们的字节码是没有区别的。如果我们再深入一层去看JIT之后的跟CPU强相关的指令,应该会发现不同。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值