jvm内存初步了解

最近学习一下多线程,所以了解一下线程不安全原因以及底层实现:

jvm组成

 

class Content :是由类加载器把class文件加载到内存中的一块内存,与class文件的区别只是存放的地址不同,内容完全一样,class文件放在硬盘上,classContent在内存中。

class对象:是由类加载器对classContent解析出的对象,存放在方法区中。

方法区(一种规范,以下两种实现不能共存):

  永久代:在堆上,jdk1.8之前用

  元空间:在直接内存里,最小20M,最大无穷,元空间最小最大一般设置成一样的,防止内存抖动,设置成物理内存的1/32

虚拟机栈:默认1M,每创建一个线程,就会创建一个虚拟机栈。

  栈帧:在一个线程中每调用一个方法就会创建一个栈帧。

  栈帧的组成:

 

 

局部变量表的大小在编译期就确定了

 

java跨平台:jvm是基于内存的,java文件由javac编译成.class文件到硬盘上。

分析下面一段代码:

 

 结构:

运行的时候这就是一个线程,因此创建了一个虚拟机栈。

变量j的内容,也就是new出来的东西在堆内存中,而指向这个变量的指针,也就是j 存放在方法区中,方法区中存放的是一个内存地址,与堆内存中这个变量的内存地址一致。

4个方法:init,clinit,main,add。

 

 

动态链接存的是类方法的直接地址,上边这个类编译解析后的方法区中有4个方法(init,main,add,clinit)

在main方法中,j2是局部变量,j2指向的是堆内存中的对象。

在add方法中,局部变量有两个但却占用3个slot,原因是在0的位置是this指针,所有非静态方法的局部变量0的位置都是 this指针

a怎样实现赋值的?

首先,局部变量表在index=1的位置创建a,操作数栈把10压入栈顶,然后操作数栈pop栈顶元素复制给a,b同理,

怎么实现return a+b?

把index=1的值压入操作数栈顶,把index=2的值压入操作数栈顶,然后pop  20,pop 10进行相加,相加后的值再压入栈。

最后实现return(返回地址):

4部分:把局部变量表的指针恢复到main方法的局部变量表指针,把操作数栈的指针恢复到main方法的操作数指针,把程序计数器指向到main方法内的位置,

清空栈帧的内存。

main方法的执行流程:

操作数栈中创建压入一个空对象,然后复制这个空对象并压入,然后pop出这个对象复制给init方法局部变量index为0的this,然后继续pop出对象复制给main方法局部变量index为1的j2,此时操作数栈为空。。。

下图的前4步就是new一个对象的过程。

下图main方法还执行了一个打印操作,跟上图代码稍有区别。

 

 

这里查看字节码用的是java Bytecode Editor,下载后运行jbe.sh,打开class文件。

eclipse找class文件位置方法:

window-show view -navigator,然后在bin目录下就是class文件,右键properties打开class文件的位置。

推荐博客:https://blog.csdn.net/sureSand/article/details/78701477

 

https://blog.csdn.net/wqq3670/article/details/105401190

posted @ 2020-05-06 18:00  ~笑春风~  阅读(217)  评论(0编辑  收藏  举报