对JVM进行回顾总结篇

1:JVM全称:Java Virtual Machine

  • JVM是一种用于计算设备的规范

按照这种规范实现的虚拟机:

  • 1:HotSpot
    – 其实在我们java1.8中就是使用这个虚拟机
    在这里插入图片描述
  • 2:JRockit
  • 3:J9M
  • 前面两种都是被oracle收购

2:JVM的体系结构:

在这里插入图片描述

  • 可以看到JVM是运行在操作系统上面,而于硬件系统进行交互的是操作系统,所以JVM于硬件没有直接的交互
3:根据《Java 虚拟机规范(Java SE 7 版)》规定,Java 虚拟机所管理的内存如下图所示。

在这里插入图片描述
1:runtime中灰色是没有回收;橙色有垃圾回收,且99%都在堆heap中
2:其实class文件有相对应的标识,并不是你随便闯一个class就可以被装载
3:类加载器相当于是jvm一个入口,在底层给操作系统进行交互的是执行引擎,这两个也就是出入口

3.1:类加载器:
  • 类加载器 负责加载class,class文件在文件开头有特定的文件表示,并且ClassLoader只负责class文件的加载,至于她是否可以运行,则由Execution Engine决定;
    在这里插入图片描述
  • 从原理图可以看到,通过ClassLoader 类加载器加载class文件后生产的CarClass 并不能直接使用,需要new,实例化;并且CarClass 被称为元数据模版;这样结合我们实际使用情况就很容易理解了;
  • 简单总结:类加载加载class文件在内存生产这个类的元数据模版,然后我们可以通过这个元数据模版来new实例化不同的对象
类加载器一共有四种:
  • 虚拟机自带的加载器
    启动类加载(bootstrap) C++:不是java的加载器,比如:在jvm启动的时候jdk那些jar的加载,其实这个是jdk自带,不属于java加载器,防止jdk中的核心被更改
    – bootstrap加载器防止原生jdk被串改,自己创建个java.lang包,创建String类;编写输出的主方法:是会看到报错:
    找不到main函数;

    原因:在这个主函数启动的时候,先是找的是启动类加载器找的String;java原生的在启动器加载器加载;像我们这样想要篡改原生的String是无法进行
    同时这个就是java的沙箱安全机制;

  • 扩展类加载器(Extension) Java
    应用程序类加载器(AppClassLoader)JAVA:也叫系统类加载器,加载当前应用的classpath的所有类

  • 用户自定义加载器:JAVA.lang.ClassLoader,用户可以定制类的加载方式
    类加载器的架构图:
    在这里插入图片描述

3.2:Execution Engine 执行引擎:
  • 与类加载器(入口)相反的就是出口:Execution Engine 执行引擎:
  • 执行引擎负责解释命令,提交给操作系统执行
3.3:Native Interface本地接口与Native Method
  • 这俩可以一起
    在这里插入图片描述
    例子:
    如果执行:new Thread().start();
    执行后线程启动没启动?:线程是操作系统去启用,所以答案是不确定
  • 查看start()方法源码:
    在这里插入图片描述
  • 可以看到 相关操作 肯定是在start0();
  • 进入start0()
    在这里插入图片描述
  • 可以看到这个方法无方法体,且是被标识的是native
  • native标识:代表这个方法是本地方法,都没有方法体,等于是给操作系统发一个消息;让操作系统启一个线程;所以操作系统可能因为资源 没启动,也有可能启动,所以不确定;
  • 又因为这个方法是本地方法,所以会被加入本地方法栈中;然后在调用本地方法接口;因为需要调用操作系统的接口,所以也是需要本地方法库
3.4:程序计数器
  • 简单来说就是这个是每个线程私有的,就是一个指针,指向方法区中的方法字节码(用来存储指向下一条指令的地址,也就是即将执行的指令代码),由执行引擎来读取下一条指令,同时这个内存空间很小;
  • 程序计数器的作用,保证了每个线程的程序方法按顺序来执行

接下来的区域需要关联记忆

3.5:方法区(Methodo Area)

在这里插入图片描述

  • 重点共享区间:简单来说都是可以共享的信息,比如加载进来的元数据模版的信息就被加载进这个方法区; 所以这个区域的生命周期比较长,垃圾回收比较少;

  • 方法区中的东西什么时候回收?:因为里面的东西一般都是一些运行环境,所以一般在jvm虚拟机停下来的时候回收;

  • 注意这个方法区,埋个坑,因为他与他下面的堆内存和java栈密切相关

3.6 Java栈(虚拟机栈)

在这里插入图片描述
生命周期快,当线程销毁了 栈也销毁了;
栈的结构:
在这里插入图片描述
栈的容量是有限的–与其相关的就是:栈溢出错误:java.lang.StackOverFlowError

比如循环调用自己就会报错这个错误;解决的方法就是找到错误的代码;

栈+堆+方法区的交互关系:

  • 接下来才讲解堆结构,简单描述与此图相关的堆内:在堆结构中的新生区中,new出来的实例全部都在这个新生区中的伊甸区,其实方法区也就是堆结构中的永久区的一个实现,所以方法区和堆是可以联系在一起
    在这里插入图片描述
  • 可以看到 ClassLoader类加载器将calss文件转化为内存中方法区的元数据模版,通过元数据模版来创建出来的实例存放在java堆中,这个实例的所以保存在java栈中,所以我们能根据这个指针找到堆中的实例,然后也可以找到方法区中的元数据模版也就是这个类->通过object.getClass()

3.7 对体系结构:

在这里插入图片描述

  • 1堆的大小是可以调节,通过参数可以进行调优
  • 可以看到分为三个区,其中每个区都是有不同的作用;
java7及以前的Heap版本:

在这里插入图片描述
简单描述:

新生区中:
  • 1:伊甸区:new出来的实例全在这里,都是在这个区new出来的
  • 2:幸存0区:从经历伊甸区gc(轻量级的垃圾回收)留下来的,一般十之八九都会被gc;在幸存1区经历过gc留下来的
  • 2:幸存1区:从0区在经历gc(轻量级的垃圾回收)留下来的,
    幸存0区和1区其实也是叫做from/to区,而且是相对的,因为默认是from/to 来回15次 还幸存的会进入养老区

from/to 是相对的额;to总为空,

养老区:
  • 在0 1 区经历默认15次gc留下来的就开始进入养老区; 所以这个对象一般都是一直在用的不会被垃圾回收
  • 不过在养老区也有gc,Major gc,全面的gc,更加深层次的gc,当养老区快满的时候就会进行更深层次的gc;不过在养老区快满了,通过 Major gc也没办法回收内存;直接就会爆over of memory Error 内存溢出OOM错误

java.lang.OutOfMemoryError:Java heap space 异常,
1 说明Java虚拟机的堆内存不够。

原因;
1:java虚拟机的内存设置不够 可以通过参数-Xms -Xmx来调整
2:代码中创建了大量的大对象,并且长时间不能被gc回收

比如在实际我们写的代码中能进入养老区的对象:
比如连接池对象常驻,会进入养老区
线程池,池对象;

永久区:

永久区与养老区是两种,并不会从养老区放入永久区,因为永久区其实就是java体系中的方法区;
在这里插入图片描述

  • 简单来说这里是: 存放jdk自带,元数据模版 … 环境,和jar包 ;存储的是运行环境必须的类信息;被装载到这里的不会被gc回收吊,关闭JVM才能释放次内存
    总结就是永久区就是jvm的环境,所以不会回收
  • java.lang.OutOfMemoryError:PermGen space 异常,
    1 引入的jar包太多,爆满;以前会现在不会,因为现在用的是maven工程,会根据你实际情况下载所对应的jar包,不会各种版本的jar包都出现 然后把永久区的jar包出现
  • ==java 8 无永久区 ==在元空间;元空间依然在方法区中,
    一个方法区接口依然有两个不同实现,一个是永久区,一个是元空间
    所以在java 8 之后都是叫元空间
堆结构内存相关图:
  • Sun HotSpot 内存管理:
    在这里插入图片描述
    可以看:堆物理上只是被分为新生区和养老区,永久区是虚线哪里,对应的是java体系架构的方法区,主要存放的是元数据模版;所以逻辑上是三个区,物理上是两个区

所以方法区和堆其实是可以联系起来的;

那永久区和方法区的关系是什么:

比如在写service层的接口时,一个接口可能会有多个实现,多个实现之间可能不一样

所以按照上面来谈:永久区可以说是方法区的具体实现,方法区就是永久区的接口,

在新生区中eden区的内存会更大些,因为eden区放new出来的对象,大概的比例8:1:1,s0,s1少是因为gc后幸存下来非常少;

  • 这些比例我们都可以在堆的参数调优可一看明白
  • 养老区与新生区中每一块比 都大,因为养老区中的幸存的对象很顽强,一般都是常驻内存,经常使用的对象;

方法区的总结:

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值