JAVA JVM内存结构

JVM内存模型包含:堆、栈、方法区、程序计算器、本地方法区。

堆:

堆是存放的是在程序运行中new出来的对象,里面包含了4个区,伊甸区、from、to、老年代。

  1. 首先new出来的对象先进伊甸区
  2. 然后当伊甸区满的时候,会触发gc,然后伊甸区存活下来的会进入from,这个时候伊甸区和to是空的
  3. 当第二批伊甸区满的时候,在次触发gc(这里gc包含from也会gc),然后会与from一起迁移到to,这个时候from是空的,伊甸区也是空的
  4. 第三批伊甸区满的时候,触发gc(这里gc包含to也会gc),然后伊甸区与to一起迁移到from

一直来加15次(默认,可设置),这时还存活的对象并会放入老年代。

如果老年代满的时候,系统会触发full gc,这个gc会很耗性能。可能会出现STW现象,机率还挺高的。

栈:

栈存放着一组栈帧,栈帧可以理解为所对应的方法进出栈的过程,栈帧里面包含了:局部变量表、操作数栈、动态链接、方法出口

局部变量表:存放栈帧里所产生的对象值

操作数栈:存放在执行过程中计算产生的值

动态链接:是指在执行过程中,需要用到局部变量表里引用对象,并且执行这个对象的代码的时候,而这个对象是通过指向所对应的类元信息获取怎样执行,这个动态指向理解为动态链接。

方法出口:指在执行过程中,引用了对象的并执行这个对象的方法并返回的时候,程序计算器所指向的下一个地址,简单的说其实就是保存现场。

例:

这个是java代码,我们通过这个java文件生成一个反汇编文件,可通过javap生成

现在我们看这上文件,是不是跟我们的java文件结构挺类似的。

这个是我们java的构造方法:

aload_0:代表把局部变量的第1个变量加载到操作数栈顶。这个第一个变量代码this。

invokespecial:代表着调用超类构造方法,这里#1所代表的是在当前类常量池中的1号元素,这个1号元素是什么呢,就是这个Method java/lang/Object."<init>":()V,返回为void的object.init方法,这里执行需要2字节的操作数,所以这里的1->4跳过了2个字节

然后返回

然后我们看第二个方法,这个是我们所说的main方法:

getstatic:获取当前类常量池中的2号元素的静态域,并将其值压入栈顶,这里所指的是Field java/lang/System.out:Ljava/io/PrintStream; PrintStream的out字段。这里面L代表的是类实例

ldc:将3号元素从常量池中推送到栈顶。这个元素就是

invokevirtual:调用4号元素所指向的实例方法

invokestatic:调用5号元素所指向的静态方法,并压入栈顶

fstore_1:将栈顶的元素,存放到第2个局部变量(第一个局部变量是this)

getstatic:同上

ldc:同上,但是它指向的元素是

iconst_1:将int型的1推送到栈顶

anewarray:创建一个元素7的类,并将其引用值压入栈顶

dup:复制栈顶数值并将复制值压入栈顶

iconst_0:将int型的0推送到栈顶

fload_1:将局部变量表中的第2个值加载到栈顶

invokestatic:调用8号元素的静态方法,这个静态方法是Float.valueOf:F

aastore:将栈顶引用型数值存入指定数组的指定索引位置

invokevirtual:调用9号元素的实例方法,这个方法是printf:PrintStream

pop:栈顶数值出栈 (该栈顶数值不能是long或double型)

return

 

然后我们看5号元素所指向的静态方法

iconst_1:将int类型1推送到栈顶

istore_0 :将栈顶int型数值存入第一个局部变量

getstatic:获取当前类常量池中的2号元素的静态域,并将其值压入栈顶,这里所指的是Field java/lang/System.out:Ljava/io/PrintStream; PrintStream的out字段。这里面L代表的是类实例

ldc:同上,只是这个元素是10,指的是

iconst_1:将int类型1推送到栈顶

anewarray:创建一个元素7的类,并将其引用值压入栈顶

dup:复制栈顶数值并将复制值压入栈顶

iconst_0:将int类型0推送到栈顶

iload_0:将int类型的第一个全局变量推送到栈顶

invokestatic:调用11号元素的静态方法。这里指的是Integer.valueOf:I

aastore:将栈顶引用型数值存入指定数组的指定索引位置(应该说的是把float.valueOf后的值放到栈顶)

invokevirtual:调用9号元素的实例方法。这里指的是printf:PrintStream

pop:栈顶数值出栈 (该栈顶数值不能是long或double型)

iconst_2:将int类型2推送到栈顶

istore_1:将栈顶int型数值存入第二个局部变量

getstatic:获取当前类常量池中的2号元素的静态域,并将其值压入栈顶,这里所指的是Field java/lang/System.out:Ljava/io/PrintStream; PrintStream的out字段。这里面L代表的是类实例

ldc:同上,只是这个元素是10,指的是

iconst_1:将int类型1推送到栈顶

anewarray:创建一个元素7的类,并将其引用值压入栈顶   

dup:复制栈顶数值并将复制值压入栈顶

iconst_0:将int类型0推送到栈顶

iload_1:将int类型的第二个全局变量推送到栈顶

invokestatic:调用11号元素的静态方法。这里指的是Integer.valueOf:I

aastore:将栈顶引用型数值存入指定数组的指定索引位置

invokevirtual:调用9号元素的实例方法。这里指的是printf:PrintStream

pop:栈顶数值出栈 (该栈顶数值不能是long或double型)

iload_0:将第一个全局变量加载到栈顶

iload_1:将第一个全局变量加载到栈顶

iadd:将栈顶2个int型数值相加,并把结果存放到栈顶

i2f:将栈顶的int型强转成float,并把结果存放到栈顶

fconst_2:将float型2推送到栈顶

fdiv:将栈顶的2个float数相除,并把结果存放到栈顶

fstore_2:把栈顶的float存放到第三个全局变量中

fload_2:加载float型第三个的全局变量的值到栈顶

freturn:返回栈顶的float值

 

这3个方法的全局变量表和操作数栈大致这样的:

方法区(元空间):

这个主要存放静态变量、常量、类元数据信息等。

程序计算器:

这个指的是程序运行中,所指向的下一个地址。

反编译文件前面的数字是所说的地址

本地方法区:

这个指的是存放native的方法区

像这类的方法

 

 

 

一些jvm的指令集可查看:

  1. https://www.jianshu.com/p/bc91c6b46d7b
  2. https://blog.csdn.net/zhangpan19910604/article/details/52254053

昨天刚看了一些资料,欢迎吐槽~~~~~~!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值