首页 > 编程知识 正文

jvm线程内存模型,java对象方法在内存模型

时间:2023-05-05 01:35:46 阅读:23700 作者:4190

JAVA8 JVM内存模型

内存分配分析publicclassmathtest { publicstaticvoidmain [ ] args } { math math=new math (); int a=2; int b=3; intc=math.plus(a,b ); c=math.mult(c; intd=math.plusandmult (2,3 ); 公共类匹配{公共int plus (inta,int b ) } /一种方法返回堆栈帧区域a b; }publicintegermult10(integera ) {返回a* 10; }publicintegerplusandmult(inta,int b ) returnmult10 ) plus,b ); }首先,让我们看看与MathTest对应的字节码信息

MathTest字节码main0new #2top/wuweij/JVM/math 3d up4invokespecial #3top/wuweij/JVM/math.init 7a store _ 18ic onst _ 29 istore _ 210 bipush 712 istore _ 313 a load _ 114 iload _ 215 iload _ 316 invokevirtual # 4 toal math.plus 19 istore 421 a load _ 122 iload 424 invoke static #5Java/lang/integer.value of 27 invokevirtual #6top/wuweij integer.intvalue 33 istore 435 a load _ 136 iconst _ 237 iconst _ 338 invokevirtual #8top/wuweij/JVM/math.lang/integer

执行命令java MathTest 1。 确定是否加载了class。 如果没有的话就加载class。 (此时将MathTest的信息加载到方法区域/元空间中。 )2.分配内存。 )没有实例化main方法的MathTest不会为堆分配内存,因此this不存在。 )3.执行线程首先将堆栈帧0分配给main方法,此时开始执行main方法。 (从方法区域/元空间获取)此处称为静态链接。 此时,main方法的所有局部变量都是从位置访问的。 与数组类似。 需要说明的是,如果方法不是静态方法,则局部变量表的第一个位置必须为this。 这意味着常规方法可以使用this,静态方法没有this。因为Math math=new Math ()此时的所有指令都是在操作数堆栈上完成的,所以操作数堆栈开始为空,指令程序卡程序计数器用于在垃圾收集器中进行垃圾收集(STW)或线程挂起后返回现场。

0 new #2top/wuweij/JVM/math 3d up4invokespecial #3top/wuweij/JVM/math.init 7a store _1new #2top/wuweij/JVM/否则,必须首先执行适当的类加载处理。

在语言级别上,new指令对应于new关键字、对象克隆、对象序列化等。

类加载检查此时,实际上给堆栈分配参考地址,给堆栈分配Math空间,并将参考地址指向Math。 必须为堆分配空间,并且堆由所有线程共享,因此存在并发问题。 jvm分配内存策略:

如何分割内存(“指针碰撞”(Bump the Pointer ) )缺省为指针碰撞)、重试异常(“空闲列表”(Free List )如何解决并发问题(CAS ) compareandswap ) )虚拟妈妈在本地线程分配缓冲区(Thread Local Allocation Buffer,TLAB )中,每个线程预装在Java堆中

先分配一小块内存。通过­XX:+/- UseTLAB参数来设定虚拟机是否使用TLAB(JVM会默认开启­XX:+UseTLAB),­XX:TLABSize 指定TLAB大小。 初始化。

内存分配完成后,虚拟机需要将分配到的内存空间都初始化为零值(不包括对象头),如果使用TLAB,这一工作过程也可以提前至TLAB分配时进行。这一步操作保证了对象的实例字段在Java代码中可以不赋初始值就直接使用,程序能访问到这些字段的数据类型所对应的零值。

设置对象头

初始化零值之后,虚拟机要对对象进行必要的设置,例如这个对象是哪个类的实例、如何才能找到类的元数据信息、对 象的哈希码、对象的GC分代年龄等信息。这些信息存放在对象的对象头Object Header之中。在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header)、 实例数据(Instance Data) 和对齐填充(Padding)。 HotSpot虚拟机的对象头包括两部分信息,第一部分用于存储对象自身的运行时数据, 如哈 希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时 间戳等。对象头的另外一部分是类型指针,即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。

dup 这个指令为复制栈顶的值,压如栈顶,也就是复制math 的引用,这里没有发现有什么作用,哪位大佬可以解释一下。invokespecial #3 <top/wuweij/jvm/Math.<init>> 执行方法 (执行构造方法)

执行<init>方法,即对象按照程序员的意愿进行初始化。对应到语言层面上讲,就是为属性赋值(注意,这与上面的赋零值不同,这是由程序员赋的值),和执行构造方法。

astore_1 把栈顶值存如局部变量表 1 位置,然后从操作数栈中移除。 5. 开执行 int a = 2; 8 iconst_2 把常量2压入操作数栈中9 istore_2 把操作数栈中的值存入局部变量表 2 的位置, 然后出栈。 6. int b = 7; 10 bipush 7 把常量7压入操作数栈中。12istore_3把 操作数栈中的值存入局部变量表3的位置。 7. int c = math.plus(a, b); 13aload_1 把局部变量表1的值压入栈中14 iload_2 把局部变量表2的值压入栈中15 iload_3把局部变量表3的值压入栈中16 invokevirtual #4 <top/wuweij/jvm/Math.plus> plus 方法0 iload_11 iload_22 iadd3 ireturn

调用对象的实现方法,这个时候通过动态链接来获取该方法,这个时候又会重新生成一个新的栈帧1 里面的结构和栈帧0一样,栈帧1 执行完以后通过方法出口返回到栈帧0中,方法执行完成。

19 istore 4 把 操作数栈中的值存入局部变量表4中。

剩下的就都差不多了,这里就不在分析了。

总结

通过对JVM的内存模型结合字节码分析了java程序的整体运行流程,总体上看,jvm把内存分为了堆和栈两大块,
栈的特点为:线程安全,不存在锁竞争的问题,即用即回收,所有不需要垃圾回收。
堆的特点为:线程不安全,所有存在锁竞争问题,需要垃圾处理器来回收垃圾,我们平时说的对JVM的调优优化也主要针对堆的调优。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。