jvm1--内存结构

一、JVM与系统

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rVhN9YdM-1616240124968)(images/1559219896(1)].jpg)

JVM是运行在操作系统之上的,他与硬件没有直接的交互。

二、JVM体系结构

在这里插入图片描述

1. Class Loader类加载器

负责加载class文件,class文件在文件开头有特定的文件标示,并且ClassLoader只负责class文件的加载,值与他是否可以允许,则由Execution Engine决定
在这里插入图片描述
classd到Class类的模板

2. Native Interface 本地接口

  • java语言本身不能对操作系统底层进行访问和操作,但是可以通过JNI接口调用其他语言(C、C++)来实现对底层的访问。

3. Execution Engine执行引擎

  • 负责解释命令,提交操作系统执行

4. Runtime data area(运行时数据区)

---------以下为运行时数据区-----------

1). Native Method Stack 本地方法栈

java在内存中专门开辟了一块区域处理标记为native的代码,他的具体做法是Native Method Stack中登记native方法,在Execution Engine执行时加载native libraies。

2). heap 堆

3)Method Area方法区

方法去是被所有线程共享,所有字段和方法字节码、以及一些特殊方法如构造函数,接口代码也在此定义。简单说,所有定义的方法的信息都保存在该区域,此区属于共享区间。用来保存装载的类的元结构信息。

静态变量+常量+类信息+运行时常量池存放在方法区

实例变量存在堆内存

4)PC Register 程序计数器

每个线程都有一个程序计数器,就是一个指针,指向方法区中的方法字节码(下一个将要执行的指令代码),有执行引擎读取下一条指令,是一个非常小的内存空间,可以忽略不记

栈管运行,堆管存储

5)Java Stack 栈

栈也叫栈内存,主管Java程序的运行,是在线程创建时创建,它的生命期是跟随线程的生命期,线程结束栈内存也就释放,对于栈来说不存在垃圾回收问题,只要线程一结束该栈就Over,生命周期和线程一致,是线程私有的。基本类型的变量、实例方法、引用类型变量都是在函数的栈内存中分配

注意:

栈管运行,堆管存储
在这里插入图片描述
对象类型数据即是 Class,类模板信息。这样堆中的实例属性字段才是一样的。

三、栈(Stak)

栈也叫栈内存,主管Java程序的运行,是在线程创建时创建,它的生命期是跟随线程的生命期,线程结束栈内存也就释放,对于栈来说不存在垃圾回收问题,只要线程一结束该栈就Over,生命周期和线程一致,是线程私有的。基本类型的变量、实例方法、引用类型变量都是在函数的栈内存中分配

3.1 栈存储什么

先进后出,后进先出即为栈

栈帧中主要保存3类数据

  • 本地变量(Local Variables):输入参数和输出参数以及方法内的变量;
  • 栈操作(Operand Stack):记录出栈、入栈的操作;
  • 栈帧数据(Frame Data):包括类文件、方法等。

3.2 栈运行原理

栈中的数据都是以栈帧(Stack Frame)的格式存在,栈帧是一个内存去块,是一个数据集,是一个有关方法(Method)和运行期数据的数据集,

当一个方法A被调用时就产生一个栈帧F1,并被压入到栈中,

A方法调用了B方法,于是产生栈帧F2也被压入到栈,

B方法调用了C方法,于是产生栈帧F3也被压入到栈。。。

执行完毕后,先弹出F3,再弹出F2,再弹出F1.。。。

遵循“先进后出/后进先出”的原则。
在这里插入图片描述

图示在一个栈中有两个栈:

栈2是最先被调用的方法,先入栈,

然后方法2调用了方法1,栈帧1处于栈顶的位置,

栈帧2处于栈底,执行完毕后,依次弹出栈帧1和栈帧2,

线程结束,栈释放。

每执行一个方法都会产生一个栈帧,保存到栈(后进先出)的顶部,顶部栈就是当前的方法,该方法执行完毕后会自动将此栈帧出栈。

四、堆(Heap)

4.1 堆内存

新生区:伊甸区 s0 s1
老年代

4.2 新生区

新生区是类的诞生、成长、消亡的区域,一个类再这里产生,应用,最后被垃圾回收器收集,结束生命。
新生去又分两部分:伊甸区(Eden Space)和幸存者区(Survivor Space),所有的类都是再伊甸区被new出来。幸存区2个:0区和1区。

4.3 养老区

养老区用于保存从新生区筛选出来的JAVA对象,一般池对象都在这个区域活跃。

5、 永久区

永久存储区是一个常驻内存区域,用于存放JDK滋生所携带的Class,Interface的元数据,也就是说它存储的是运行环境必须的类信息,被装载进此区域的数据是不会被垃圾回收器回收掉的,关闭JVM才会释放此区域所占用的内存。

5.1定义

逻辑上是堆的一部分,但是jvm厂商实现不一定遵从

5.2结构

idk1.6
在这里插入图片描述
因为串池用的很频繁,但是只有老年代不足时才会触发FULLGC,这样的频率不高,容易造成溢出,所以将它转移到了堆内存中
在这里插入图片描述

5.3运行时常量池

1)常量池,就是一张表,虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量等信息
在这里插入图片描述
2)运行时常量池,常量池是 *.class 文件中的,当该类被加载,它的常量池信息就会放入运行时常量池,并把里面的符号地址变为真实地址
上图中的#1、2等会变成运行时的真实地址

5.4 StringTable 特性(串池)

1)常量池中的字符串仅是符号,第一次用到时才变为对象
2)利用串池的机制,来避免重复创建字符串对象
3)字符串变量拼接的原理是 StringBuilder (1.8 new对象在堆里)
4)字符串常量拼接的原理是编译期优化
5)可以使用 intern 方法,主动将串池中还没有的字符串对象放入串池
6)1.8 将这个字符串对象尝试放入串池,如果有则并不会放入,如果没有则放入串池, 会把串池中的对象返回
1.6 将这个字符串对象尝试放入串池,如果有则并不会放入,如果没有会把此对象复制一份,放入串池, 会把串池中的对象返回
在这里插入图片描述s3==s5!=s4

5.5 StringTable优化

因为StringTabl底层是hashtable,调整桶个数会影响入池的效率。桶太少,链表长发生hash碰撞概率大。效率慢。
调整 -XX:StringTableSize=桶个数(默认60000)

6、直接内存

6.1、定义

常见于 NIO 操作时,用于数据缓冲区
分配回收成本较高,但读写性能高
不受 JVM 内存回收管理
在这里插入图片描述

在这里插入图片描述
普通io和nio
nio在系统内存中开辟出直接内存,java可以直接访问,更快

6.2 分配和回收原理

使用了 Unsafe 对象完成直接内存的分配回收,并且回收需要主动调用 freeMemory 方法
ByteBuffer 的实现类内部,使用了 Cleaner (虚引用)来监测 ByteBuffer 对象,一旦
ByteBuffer 对象被垃圾回收,那么就会由 ReferenceHandler 线程通过 Cleaner 的 clean 方法调
用 freeMemory 来释放直接内存

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值