JVM基础 ----跟着狂神学习系列

JVM的位置

在这里插入图片描述

JVM的体系结构

在这里插入图片描述

类装(加)载器

作用:加载class文件 通过new()实例
类是模板,对象是具体的
在这里插入图片描述

1、虚拟机自带的加载器
2、启动类(根)加载器
3、扩展类加载器
4、应用程序加载器

沙箱机制

详细见:
https://blog.youkuaiyun.com/qq_30336433/article/details/83268945

双亲委派机制

目的:安全
路径: BOOT —> EXC —>APP (最终执行)
1、类加载器收到加载的请求
2、将加载请求向上委托给类加载器去完成,一直向上委托,知道启动类加载器
3、启动加载器检查是否能够加载当前这个类,能加载就结束,使用当前加载器,否则,抛出异常,通知子类加载器进行加载
4、重复步骤 3
null : Java调用不到或不存在

native(本地的)

1、凡是带了native关键字的,说明Java的作用范围达不到了,回去调用底层c语言的库
2、会进入本地方法栈(native method stack)
3、调用本地方法接口(JNI)
4、Java诞生的时候为了立足,必须调用有c、c++程序
5、JNI的作用:扩展Java的使用,融合不同的编程语言为Java所用
6、内存区域中专门开辟一块区域本地方法栈,用来登记native方法
7、在最终执行的时候,通过JNI加载本地方法库中的方法
8、Java程序驱动打印机,管理系统,在企业中较为少见

PC寄存器

程序计数器:program counter register
每个线程都有一个程序计数器,是线程私有的,就是一个指针,指向方法区中的方法字节码(用来储存指向像一条指令的地址,也即将要执行的指令代码),在执行引擎读取下一条指令,是一个非常小的空间,几乎可以忽略不计

方法区

1、方法区是被所有线程共享的,所有字段和方法字节码,以及一些特殊的方法,如:构造函数,接口代码也在此定义,简单来说,所有定义的方法的信息都保存在该区域,此区域属于共享区域
静态变量、常量、类信息(构造方法,接口定义)、运行时的常量池存在方法区中,但是,实例变量存在堆内存中和方法区无关
即static,final,class,常量池
2、方法区在逻辑上属于堆的,即特点性质上相似,但本质上属于是管理堆外的内存,所以也叫非堆
3、方法区存在于元空间
##栈
栈是一种数据结构,栈:栈内存,主管程序的运行,生命周期与线程同步;线程结束,栈内存也就释放,所以对于栈来说,不存在垃圾回收问题,一旦线程结束,栈就死亡
栈:先进后出 队列:先进先出 (FIFO:first input first outout) —> 喝多了吐是栈,吃多了拉是队列
在这里插入图片描述

例:main方法先执行,最后结束
在这里插入图片描述

栈的原理:栈帧
栈满了:StackOverflowError这是个错误不是异常。程序无法自动解决,只能终止
在这里插入图片描述

栈+堆+方法区 :交互关系
在这里插入图片描述

补充:JAVA是值传递

三种JVM

SUN公司 HotSpot ---->当前使用的
BEA JRockit
IBM J9 VM

Heap,一个JVM只有一个堆内存,堆内存大小是可以调节的
实例变量在堆内存中
在这里插入图片描述

GC垃圾回收,主要在伊甸园区和养老区
假设内存满了。会报OOM:OutOfMemoryError的错误,内存不够
幸村区可以看作是新生区与养老区间的过渡区域

新生区

新生区是对象诞生,成长,死亡的地方
所有对象都是在伊甸园区new出来的
幸存者区的from…to也可以理解为,两个幸村区中,一个为幸存1区,一个为幸存0区,二者相互交互,from和to的位置0区和1区变化着
谁空谁是to,谁有足够大的空间,谁变为to区

老年区(Tenured)

新生区杀不死的去往老年区

永久区 (Perm)

这个区域常驻内存,用来存放JDK自身携带的Class对象,interface元数据,存储的是Java运行时的一些环境或者类信息,这个区域不存在垃圾回收,关闭VM虚拟就会释放这个区域的内存
一个启动类,加载了大量的第三方jar包,Tomcat部署了太多的应用,大量动态生成的反射类,不断的被加载,直到内存满,就会出现OOM

  • jdk1.6前,永久代,常量池在方法区
  • jdk1.7,永久代,但慢慢退化,去永久代,常量池在堆中
  • jdk 1.8后,无永久区,常量池在元空间

新生区,永久区,堆内存调优

在这里插入图片描述

元空间逻辑上存在,物理上不存在:
因为元空间物理空间上是在本机内存而不是虚拟机内存,所以实际上的堆内存在数值上是新生代和老年代的总和

调优(调节堆内存大小):
默认情况下,分配的总内存是电脑内存的 1/4,而初始化的内存是电脑的 1/64
// 返回虚拟机试图使用的最大内存 .maxMemory() ; 返回JVM的总内存 .totalMemoty()
// 返回值是 long类型,返回单位是字节

OOM:
1、尝试扩大内存看结果
2、分析内存,看哪个地方出问题(专业工具)
例: -Xms1024m -Xms1024m -XX:+PrintGCDetails -->在调试中的VM选项,运行程序后会打印出信息
Xms 是指设定程序启动时占用内存大小,Xmx 是指设定程序运行期间最大可占用的内存大小,Xss 是指设定每个线程的堆栈大小
可以在数字后面添加 [k/K]或者 [m/M]来表示KB或者MB

使用idea-JPofiler工具分析OOM的原因

eclipse中是通过MAT;
作用:

  • 分析Dump内存快照,快速定位内存泄漏
  • 获得堆中的数据
  • 获得大的对象

GC

作用区域:方法区,堆
种类:轻GC (普通GC) ,重GC(全局GC)
GC的算法:标记-清除算法,标记-压缩(整理)算法,复制算法,引用计数算法

引用计数算法(低效,使用少)

给每个对象赋予一个计数器,根据使用次数赋值,次数少的被清除
在这里插入图片描述

复制算法

每次GC都会将Eden活的对象移到幸存区中,一旦Eden区被GC后,就会是空的
当一个对象经历了15次GC(默认值),都还没有死,就会进入老年区
-XX:MaxTenuringThreshold = 15 //通过这个参数可以设定进入老年代的时间 ,标志位只有四位–>最大只能是15
复制算法就是from和to相互变换时,复制原to中的数据带到新的from中
好处:没有内存碎片
坏处:浪费了内存空间—多了一半空间永远是空 to , 所以假设对象100%存活(极端情况),会增加复制成本
适用情况:对象存活度较低 —>新生区

标记清除压缩

先标记清除几次,再压缩

标记-清除算法

在这里插入图片描述

缺点:两次扫描,时间成本;标记成本,清除后占用空间不变,会产生内存碎片(非连续的内存空间)
优点:不需要额外的空间

####标记-压缩算法
压缩:清除后的占用空间会被标记的对象占用
缺点:多了压缩成本
优点:防止内存碎片的产生

GC算法总结

内存效率: 复制算法>标记清除算法>标记压缩算法(时间复杂度)
内存整齐度:复制算法 =标记压缩算法 > 标记清除算法
内存利用率:标记压缩算法 = 标记清除算法 > 复制算法

没有最好的算法只有最合适的 ----->GC:分代收集算法

  • 年轻代:存活率低 —>复制算法
  • 老年代 : 区域大,存活率高 —>标记清除压缩
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值