jvm 之堆

内存堆:分为,老年代(2/3)和年轻代(1/3),如果给堆分配600m的内存,老年代占400m,年轻代占200m, 

年青代分为,eden(8/10)和suriver(2/10),eden占160m,suriver占40m

 suriver:分为 from(1/10)和to(1/10),from是20m,to是20m

math.java 执行过程

1:java通过编译器转译成.class(字节码文件)

2:类加载子系统加载字节码文件

3:字节码引擎执行字节码文件。开辟线程,

4:首先会在栈内存开辟一个 该线程的堆空间,然后会在该堆空间,开辟栈帧空间,(该线程内多少方法会,开辟多少栈帧空间,栈帧空间存的是该方法的变量。例如 int a=1;  存的是 int a),局部变量存放的位置叫做局部变量表。

5:栈帧空间内有,局部变量表,操作数栈,数据连接,方法出口

6:字节码执行引擎执行 字节码文件的时候,执行线程的时候,

第一:先在栈空间开辟一个此线程栈空间,通过字节码执行引擎执行字执行方法的时候,

第二:会在此线程空间内分配一个 栈帧空间,

第三:当执性变量时:如果是基本类型,

    1:会把数值1,压到操作数栈中

    2:会先把变量的引用(int a=1) a存放到局部变量表内。

   3:把操作数栈的1出栈,移动到局部变量表中,的a赋值,局部变量表  a=1;

第四:如果变量是:引用变量,

   1:首先会把变量的引用,放到局部变量表内

   2:对象放到堆内存中。

第五:如果有静态变量和常量,类信息,是放在,方法区内。

例子:math类

有两个静态变量,一个静态基本类型,一个静态引用类型,静态变量和数值都放在方法区内(??,记不得了,)

执行主方法main,然后会在线程内开辟该线程栈空间,再在该线程栈空间,开辟一个main方法的栈帧空间,当执行 

math math=new math()时,先把变量math存到 main栈帧内的局部变量表内,然后再把 new math()对象存到堆内存中,

math 调用一个compute方法,会在开线程占空间开辟一个属于compute的栈帧空间,然后再main的方法出口指向compute方法,

第二:执行compute方法时,

   1:先把a存到 局部变量表,再把a对应的值1存放到操作数栈

   2:先把b存到 局部变量表,再把b对应的值2存放到操作数栈

   2:先把c存到 局部变量表,再把a的值,和b的值复制一份然后进行运算,存放到操作数栈里

return c是指向main栈帧空间内的方法出口

GC Root 可达性算法,复制算法:个人理解, 堆内存的是对象,当对象没有可用指针就是垃圾对象,就要被清除,GCroot就是从起始对象开始然后到最后一个对象。比如main方法调用compute方法 ,那么GCroot只有 main方法和conpute。

第二:堆内存,所有的对象常见时,都放在新生代的eden区域,当eden区域满时,会执行minor GC,回收,(在这里应该通过gc root查看哪些对象没有用,是垃圾对象,直接清除 ,如果对该对象正在使用,会把对象从eden,放到from区域(该对象标识加1,此表示是判断该对象经过几次垃圾minorGC  还存活,存过15次,会把对象存放到老年代中,此区域的对象是经常存活的对象)),当第二次eden区域满时,在进行minorGC。

1.1:eden区域的垃圾对象清除,活着的对象移动到from区域,

1.2:form区域的对象,也进行判断,没有用的对象被清除,活着的对象移动到to区域,分代年龄加1.

1.3:to 区域的对象,也进行判断,没有用的对象被清除,活着的对象移动到from区域,分代年龄加1.

知道有的对象经历过15次清除,还活着,移动到老年区域。

当老年代区域的内存满时,需要进行full gc 清除,它会清除老年代内存中没有被用到的对象,和方法区的数据。

程序计数器:当前程序运行的行号,(每个线程都有),是一个内存区域,存的是当前线程的运行代码的行号。

为什么会有程序计数器?,因为线程时切换的,当a线程执行到100行代码时间,执行b线程,然后切到a线程的时候,就从100行再继续执行,--就是这个作用

发布了143 篇原创文章 · 获赞 41 · 访问量 59万+

猜你喜欢

转载自blog.csdn.net/qq_29257691/article/details/103616370