Java内存模型(JMM)和 Java 运行时内存区域区别可大了呢,不要走开接着往下看,答应我要看完。 为什么要有内存模型? 要想回答这个问题,我们需要先弄懂传统计算机硬件内存架构。...使用高速缓存解决了 CPU 和主存速率不匹配的问题,但同时又引入另外一个新问题:缓存一致性问题。 ?...不同的线程之间无法直接访问对方本地内存中的变量。 看文字太枯燥了,我又画了一张图: ?...use:使用。作用于工作内存的变量,把工作内存中的一个变量值传递给执行引擎,每当虚拟机遇到一个需要使用变量的值的字节码指令时将会执行这个操作。 assign:赋值。...作用于工作内存的变量,它把一个从执行引擎接收到的值赋值给工作内存的变量,每当虚拟机遇到一个给变量赋值的字节码指令时执行这个操作。 store:存储。
答: a是变量,变量可读可写,只能在RAM里。123是要写入的值,地址在链接程序时分配的,要查看分配的是哪个地址可以运行的时候调试查看。 11....问:p = (volatile unsigned int *)(0x40010800 + 0x0c)中的volatile unsigned in可以不写吗? 答: 可以不写,会有警告。 14....CPU内部的寄存器,GPIO上的寄存器,完全不是一回事: CPU里面的寄存器,使用汇编指令来读写; GPIO上的寄存器,像内存一样,CPU发出地址信号、数据信号,来读写它; 18....可以,用pack指令,具体用法可以百度搜索。 26. 问: cortex-m系列我可以理解为代码位于Flash上,变量位于RAM上吗?这样从Flash取指令速度会不会受限?...①对于上图的变量a,可以一次性读、写完;②对于上图的变量b,要读2次:第1次读得到下图椭圆中的4字节: 第2次读,得到下图椭圆中的4字节: 然后组合下图中的椭圆中的内容:
而一些使用虚拟机的语言如Lua,Java等。OpCode和逻辑代码是一一对应的,GC相关的细节被封装在虚拟机内部。 这种分层会让底层的OpCode非常清晰,对底层调优很有帮助。...这就导致一个问题,当一个线程被抢占时,他当前的整个callstack的上下文中,被使用的寄存器是不确定的。 因此在linux中的,Thread被换出时,需要保存全套的寄存器(EAX,EBX….)。...但是,后来我看到了goroutine是可以在任意时机被抢占的。 这我就不太能理解了,不管是不是Plan9汇编,最终只要跑在x86指令集的机器上,他们的优化思路都应该是尽可能多的使用寄存器,而不是栈。...我很难确定,是不是在Plan9的ABI中,每个函数只有三个寄存器可用。 在从Plan9生成X86汇编时,会把栈上变量尽可能多地转移到x86寄存器上。...这种组合方式,不仅粘合了两个struct, 还粘合了两个变量。如果用得好,也许会有出其不意的威力。 当然,天下没有白吃的午餐。
所以现在只有当代码在supervisor mode时,才可能在程序运行的同时而不崩溃。所以,从代码没有崩溃和程序计数器的值推导出我们必然在supervisor mode。...在C代码中,当你调用函数,第一个参数会存在a0,这就是为什么a0里面的数值是指向trapframe的指针。fn函数是就是刚刚我向你展示的位于trampoline.S中的代码。...毕竟我们在内存中的某个位置执行代码,程序计数器保存的是虚拟地址,如果我们切换了page table,为什么同一个虚拟地址不会通过新的page table寻址走到一些无关的page中?...寄存器保存在了trapframe page,但是这些寄存器用户程序也能访问,为什么我们要使用内存中一个新的区域(指的是trapframe page),而不是使用程序的栈?...有很多原因都可以让程序运行进入到usertrap函数中来,比如系统调用,运算时除以0,使用了一个未被映射的虚拟地址,或者是设备中断。
面试题分析 (1)为什么要使用PC寄存器记录当前线程的执行地址呢? JVM的多线程是通过CPU时间片轮转(即线程轮流切换并分配处理器执行时间)算法来实现的。...(2)PC寄存器为什么会被设定为线程私有呢? 由于jvm的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器都只会执行一条线程中的指令。...不管使用哪种方式,都会导致栈帧出栈。不同线程中所包含的栈帧是不允许存在互相引用的,即不可能在一个栈帧之中引用另外一个线程的栈帧。 ” ?...寄存器的值置为下一条指令的执行地址,即2; 当执行指令地址为2的操作指令时,将操作数栈中的数据取出来,存到局部变量表的1位置,因为该方法是实例方法,所以0位置存的是this的值,PC寄存器中的值变为3;...为什么要使用Native Method?
当一个线程向被volatile关键字修饰的变量写入数据的时候,虚拟机会强制它被值刷新到主内存中。当一个线程用到被volatile关键字修饰的值的时候,虚拟机会强制要求它从主内存中读取。...在这里我需要说明一下,有的同学可能在测试上面代码的时候程序可以正常退出。那是因为你的JVM没有优化造成的!...2.2 防止指令重排序(防止JVM编译源码生成class时使用重排序) 编译期重排序的典型就是通过调整指令顺序,做到在不改变程序语义的前提下,尽可能减少寄存器的读取、存储次数,充分复用寄存器的存储值。...,然后会加载10到数据寄存器,然后CPU通过mov指令把10写入到地址寄存器中指定的内存地址中。...然后加载y变量的内存地址到地址寄存器,加载9到数据寄存器,把9写入到内存地址中。
JVM ≠ Japanese Video's Man 写这篇的主要原因呢,就是为了能在简历上写个“熟悉JVM底层结构”,另一个原因就是能让读我文章的大家也写上这句话,真是个助人为乐的帅小伙。。。。...:使用PC寄存器存储字节码指令地址有什么用呢?为什么使用PC寄存器记录当前线程的执行地址呢? ?♂️:因为CPU需要不停的切换各个线程,这时候切换回来以后,就得知道接着从哪开始继续执行。...JVM的字节码解释器就需要通过改变PC寄存器的值来明确下一条应该执行什么样的字节码指令。 ??:PC寄存器为什么会被设定为线程私有的? ?...Slot 处,其余的参数按照参数表顺序继续排列(这里就引出一个问题:静态方法中为什么不可以引用 this,就是因为this 变量不存在于当前方法的局部变量表中) 栈帧中的局部变量表中的槽位是可以重用的...为什么要使用本地方法(Native Method)?
因此,这里就采用了不直接通过 esp,而是用 ebp 寄存器来读写栈内容的方法。 (3) 使用[ebp + 8] 指定栈中存储的第1个参数123,并将其读出到 eax 寄存器中。...全局变量和局部变量 在熟悉了汇编语言后,接下来我们来了解一下全局变量和局部变量,在函数外部定义的变量称为全局变量,在函数内部定义的变量称为局部变量,全局变量可以在任意函数中使用,局部变量只能在函数定义局部变量的内部使用...,并把结果赋值给A call A 调用函数A cmp A,B 对A和B进行比较,比较结果会自动存入标志寄存器中 inc A 对A的值 + 1 ige 标签名 和 cmp 命令组合使用。...跳转到标签行 jl 标签名 和 cmp 命令组合使用。跳转到标签行 jle 标签名 和 cmp 命令组合使用。跳转到标签行 jmp 标签名 和 cmp 命令组合使用。...大家可能认为使用高性能的寄存器来替代普通的内存是一种资源浪费,但是编译器不这么认为,只要寄存器有空间,编译器就会使用它。由于寄存器的访问速度远高于内存,所以直接访问寄存器能够高效的处理。
JVM ≠ Japanese Video's Man 写这篇的主要原因呢,就是为了能在简历上写个“熟悉JVM底层结构”,另一个原因就是能让读我文章的大家也写上这句话,真是个助人为乐的帅小伙。。。。...情况的区域 :使用PC寄存器存储字节码指令地址有什么用呢?...为什么使用PC寄存器记录当前线程的执行地址呢? ♂️:因为CPU需要不停的切换各个线程,这时候切换回来以后,就得知道接着从哪开始继续执行。...JVM的字节码解释器就需要通过改变PC寄存器的值来明确下一条应该执行什么样的字节码指令。 :PC寄存器为什么会被设定为线程私有的? ...Slot 处,其余的参数按照参数表顺序继续排列(这里就引出一个问题:静态方法中为什么不可以引用 this,就是因为this 变量不存在于当前方法的局部变量表中) 栈帧中的局部变量表中的槽位是可以重用的
写这篇的主要原因呢,就是为了能在简历上写个“熟悉JVM底层结构”,另一个原因就是能让读我文章的大家也写上这句话,真是个助人为乐的帅小伙。。。。...情况的区域 :使用PC寄存器存储字节码指令地址有什么用呢?...为什么使用PC寄存器记录当前线程的执行地址呢? ♂️:因为CPU需要不停的切换各个线程,这时候切换回来以后,就得知道接着从哪开始继续执行。...JVM的字节码解释器就需要通过改变PC寄存器的值来明确下一条应该执行什么样的字节码指令。 :PC寄存器为什么会被设定为线程私有的? ...Slot 处,其余的参数按照参数表顺序继续排列(这里就引出一个问题:静态方法中为什么不可以引用 this,就是因为this 变量不存在于当前方法的局部变量表中) 栈帧中的局部变量表中的槽位是可以重用的
比如说我设置一个变量,用来表示rax寄存器,设置另一个变量来表示rip寄存器。再设置一片内存空间来表示模拟器的内存空间。...例如虚拟机中要执行「内存0x10数据读取到rax寄存器中」这样的指令,通过虚拟化API,CPU会真实地执行一条从内存中读取数据放到寄存器中的指令。...那么在运行之前,我先读一遍原程序,比如说当它出现「把数据加载到rax寄存器中」指令的时候,我就想,嗯……虽然我的ARM架构中没有rax寄存器,但是,我可以用其他的寄存器来代替,比如说x0。...系统属性 接着,在环境变量中找到用户变量里的Path,这个变量决定了,如果你不指定绝对路径,而是直接输入一个命令的时候,系统会去哪些路径中找程序。...后面一句 mov ds, ax 则是把ax的值赋值给ds寄存器,这样ds寄存器中也是0xb800了。 相信读者在这里一定会有疑惑,为什么我不能直接mov ds, 0xb800呢?
的确,Java 虚拟机的操作码都是单字节的,其指令字总操作码个数不超过 256 条。而 Dalvik 指令则长的多的多,数量也多的多。...如果是 s,表示指令采用静态链接。如果是字母 i,表示指令应该被内联处理。 寄存器命名 我们都知道 Dalvik 虚拟机是基于寄存器架构的,其使用的寄存器都是 32 位的。...如果不是很确定,可以查看其 smali 代码中的 .registers 字段。答案是 4 个。根据 Dalvik 虚拟机规定,方法参数使用最后面的寄存器。...而剩余的开头的寄存器就是局部变量寄存器,在 add() 方法中只有一个局部变量寄存器,用于存储 a+b 的值,就是第一个寄存器。...后续我也会开源一个完整版的 Dalvik 指令集的表格。 总结 本文介绍了 Dalvik 虚拟机的相关知识,比较了 Dalvik 虚拟机和 JVM,后续着重介绍了 Dalvik 指令集。
我提供了字节码中,一些常用的指令,增加你对字节码特点的直观认识,完整的指令集可以参见 JVM的规格书: 其中,每个指令都是8位的,占一个字节,而且iload_0、iconst_0这种指令,甚至把操作数...例如,当存在公共子表达式时,这个表达式的计算结果可以保存在某个寄存器中,另一个用到该公共子表达式的指令,就可以直接访问这个寄存器,不用再计算了。...你也不需要关心寄存器的分配,因为JVM是使用操作数栈的; 指令重排序也不用考虑,因为指令的顺序是确定的,按照逆波兰表达式的顺序就可以了; 优化算法,你暂时也不用考虑。...Spring与字节码生成技术 我在开篇提到,Java程序员大部分都会使用Spring。...如果想要掌握这个技术,你需要对Java虚拟机的运行原理、字节码的格式,以及常见指令有所了解。我想强调的重点如下: 运行程序的虚拟机有两种设计:一个是基于栈的;一个是基于寄存器的。
具体来说:这两种架构之间的区别: 19.1、基于栈的指令集架构 基于栈式架构的特点: 设计和实现更简单,适用于资源受限的系统; 避开了寄存器的分配难题:使用零地址指令方式分配 指令流中的指令大部分是零地址指令...3 保存至变量 j 中 4: iload_1 // 加载变量 i 5: iload_2 // 加载变量 j 6: iadd // 执行累加操作...),那么为什么不将架构更换为基于寄存器的架构呢?...不管是现在仍在广泛使用的JDK6,还是使用比例较多的JDK8中,默认的虚拟机都是HotSpot Sun/oracle JDK和openJDK的默认虚拟机 因此本课程中默认介绍的虚拟机都是HotSpot,...GCIH中的对象还能够在多个Java虚拟机进程中实现共享 使用crc32指令实现JvM intrinsic降低JNI的调用开销 PMU hardware的Java profiling tool和诊断协助功能
前言 我一直尝试着用不一样的文字来写博客!原因很简单,你讲的知识书上都有,那么每个人为什么不选择看书而选择看你的博文来学习呢?...另外,我需要说明的一点是,程序计数器是Java虚拟机规范中唯一一个没有规定任何内存错误的区域! 虚拟机栈(Vm Stack) 这块区域是干啥的?为啥也是线程私有的?...Java虚拟机的解释执行引擎称为“基于栈的执行引擎”,其中所指的“栈”就是操作数栈。因此我们也称Java虚拟机是基于栈的,这点不同于Android虚拟机,Android虚拟机是基于寄存器的。...基于栈的指令集最主要的优点是可移植性强,主要的缺点是执行速度相对会慢些;而由于寄存器由硬件直接提供,所以基于寄存器指令集最主要的优点是执行速度快,主要的缺点是可移植性差 动态链接: 每个栈帧都包含一个指向运行时常量池...该区域与虚拟机栈所发挥的作用非常相似,只是虚拟机栈为虚拟机执行Java方法服务,而本地方法栈则为使用到的本地操作系统(Native)方法服务。
大家好,又见面了,我是你们的朋友全栈君。 马上就要找实习了,趁着现在有时间,做个小小的面试总结,部分原创,大部分是在网上搜集。 1 什么是java虚拟机(Java Virtual Machine)?...java虚拟机是一种抽象化虚拟的计算机,java虚拟机有完善的一套硬体架构,包括一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个存储方法域。...Java的8位操作码的长度使得JVM最多有256种指令,java1.6及以上版本已使用了160多种操作码。 寄存器 JVM只设置了4个最为常用的寄存器。...它们是:pc程序计数器optop操作数栈顶指针frame当前执行环境指针 vars指向当前执行环境中第一个局部变量的指针 所有寄存器均为32位。pc用于记录程序的执行。...当前,并不是在所有的平台下都有相应Java解释器程序,这也是Java并不能在所有的平台下都能运行的原因,它只能在已实现了Java解释器程序的平台下运行。
的命名源于CPU寄存器,寄存器存储指令相关的现场信息,CPU只有把数据装载到寄存器中才能运行,JVM中的PC寄存器是对物理PC寄存器的一种抽象模拟 作用:PC寄存器用来存储指向下一条指令的地址,也就是即将执行的指令代码...他是唯一一个在Java虚拟机规范中没有规定任何OutMeroryError情况的区域 虚拟机栈 由于跨平台性的设计,Java的指令都是根据栈来设计的,不同平台CPU架构不同,所以不能设计为基于寄存器的...与性能调优关系最为密切得部分就是前面提到得局部变量表,在方法执行时,虚拟机使用局部变量表完成方法得传递 - 局部变量表中得变量也是重要的垃圾回收根节点,只要被局部变量表中直接活间接引用得对象都不会被回收...这个错误如果发生在运行时,就说明一个类发生了不兼容的改变 在面向对象的编程中,会很频繁的使用到动态分派,如果在每次动态分派的过程中都需要重新在类的方法元数据中搜索合适的目标的话就可能影响到执行效率,...他甚至可以直接使用本地处理器中的寄存器 直接从本地内存的堆中分配任意数量的内存 并不是所有的JVM都支持本地方法,因为就Java虚拟机规范并没有明确要求本地方法栈的使用语言、具体实现方式、数据结构等
操作方式与数据结构中的栈相类似。 2.为什么jvm的内存是分布在操作系统的堆中呢??...2,虽说bootStrap、extclassLoader、appclassloader三个是父子类加载器关系,但是并没有使用继承,而是使用了组合关系。...,(1),区别于计算机硬件的pc寄存器,两者不略有不同。...计算机用pc寄存器来存放“伪指令”或地址,而相对于虚拟机,pc寄存器它表现为一块内存(一个字长,虚拟机要求字长最小为32位),虚拟机的pc寄存器的功能也是存放伪指令,更确切的说存放的是将要执行指令的地址...另外,图中,指令是Java代码经过javac编译后得到的JVM指令,PC寄存器指向下一条该执行的指令地址,局部变量区存储函数运行中产生的局部变量,栈存储计算的中间结果和最后结果。
其实除上面那种用组合键或者是手动的通过kill指令加信号编号的方式给进程发送信号外,我们还可以通过系统调用的方式给进程发送信号。...这一点也不难理解,用户能做的工作从权限角度来讲是比较有限的,当程序已经在CPU上跑起来的时候,此时用户是什么都无法做的,他只能在一旁看着CPU取程序的指令并执行指令,至于用户想要修改或维护此时CPU计算异常这样的事情...在进程切换时,操作系统会将新的进程的页目录表的物理地址加载到CR3寄存器中,MMU会根据新的页目录表地址进行虚拟到物理地址的转换。 3....在上面叙述的过程中,进程执行handler方法后为什么不能直接回到main执行流?而是需要先回到内核态,然后再通过某些汇编指令(iret)回到用户态,恢复main函数的上下文继续执行。...在使用sigset_t类型的变量之前,一定要使用sigemptyset()或sigfillset()函数对变量进行初始化,使变量内部的数据处于一个确定稳定的状态,在初始化sigset_t变量之后就可以调用剩余三个函数进行信号的添加
领取专属 10元无门槛券
手把手带您无忧上云