JVM的知识-看这一篇就够了

什么是JVM?

我们先看下完整的单词。JVM(Java Virtual Machine,Java虚拟机)

首先什么是虚拟机

虚拟机是一种抽象化的计算机,通过在实际的计算机上仿真模拟各种计算机功能来实现的。

虚拟机有哪几种类型

大体上虚拟机可以分为系统虚拟机和程序虚拟机。

visual Box、VMare就属于系统虚拟机。他们完全是对物理计算机的仿真,提供一个可运行完整操作系统的软件平台。

java虚拟机就是典型程序虚拟机,它专门为执行单个计算机程序而设计。
在java虚拟机中执行的指令我们称之为java字节码指令。

java虚拟机有哪几种

最初sun使用的叫Classic的java虚拟机,
到现在使用最广泛的是HotSpot虚拟机,除了sun以外还有BEA的JRockit虚拟机。


java虚拟机的基本结构图解

图片来自网络,我们先大概看下基本结构,接下来再详细讲一下。
在这里插入图片描述

JVM内存区域划分

根据上图我们可以粗略分来,JVM的内部体系结构分为三部分,
类装载(ClassLoader)子系统,
运行时数据区,
执行引擎。

1)类装载子系统

每一个Java虚拟机都有一个类加载器子系统(class loader subsystem),
负责加载程序中的类型(类和接口),并赋予唯一的名字。

JVM的两种类装载器包括:启动类装载器和用户自定义类装载器,启动类装载器是JVM实现的一部分,用户自定义类装载器则是Java程序的一部分,必须是ClassLoader类的子类。

2)执行引擎

每一个Java虚拟机都有一个执行引擎(execution engine)负责执行被加载类中包含的指令。

它或者在执行字节码,或者执行本地方法
主要的执行技术有:解释,即时编译,自适应优化、芯片级直接执行其中解释属于第一代JVM,即时编译JIT属于第二代JVM,自适应优化(目前Sun的HotspotJVM采用这种技术)则吸取第一代JVM和第二代JVM的经验,采用两者结合的方式 。

自适应优化:开始对所有的代码都采取解释执行的方式,并监视代码执行情况,然后对那些经常调用的方法启动一个后台线程,将其编译为本地代码,并进行仔细优化。若方法不再频繁使用,则取消编译过的代码,仍对其进行解释执行。

3)运行时数据区

主要包括:方法区,堆,Java栈,PC寄存器,本地方法栈

在看这个运行时数据区的时候,我们先来了解一下数据结构里面的栈和堆

栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方。与C++不同,Java自动管理栈和堆

什么是栈?

栈式先进后出的。
栈的优势是,存取速度比堆要快,仅次于直接位于CPU中的寄存器。但缺点是,存在栈中的数据大小与生存期必须是确定的。
在这里插入图片描述

什么是堆?

堆是一种常用的树形结构,是一种特殊的完全二叉树。

java的栈存储什么?

栈中主要存放一些基本类型的变量(int, short, long, byte, float, double, boolean, char),例如 int a = 3;
另外,栈有一个很重要的特殊性,就是存在栈中的数据可以共享。
例如下面的代码,a和b都是指向数值为3的地址。

int a = 3;
int b = 3;

java的堆存储什么?

堆中主要是存包装类,如Integer, String, Double等将相应的基本数据类型包装起来的类。
还有new 出来的类的实例。

好了,到这里也有大概的了解栈和堆了,现在正式看java虚拟机的运行时数据区有哪些。

1、方法区(Method Area)
存放所加载的类的信息(名称、修饰符等)、类中的静态变量;
存放类中定义为final类型的常量、类中的Field信息、类中的方法信息,

在JDK8之前的Host Spot虚拟机的实现中,方法区也被称为永久区,又称为持久代。
在 Java8 中,永久区已经被 Metaspace 元空间取而代之。
关于两者的区别和垃圾回收可以看我的这篇博客
垃圾回收详解

当开发人员在程序中通过Class对象中的getName、isInterface等方法来获取信息时,这些数据都来源于方法区域,同时方法区域也是全局共享的,在一定的条件下它也会被GC,当方法区域需要使用的内存超过其允许的大小时,会抛出OutOfMemory的错误信息。

2、java堆:
再java虚拟机启动的时候旧建立java堆,他是java程序最主要的内存工作区域,几乎所有new创建对象的实例都存放java堆中,注意:堆空间是所有线程共享的。

3、直接内存:
java的NIO库允许java程序使用直接内存,从而提高性能,通常直接内存速度会优于java堆。读写频繁的场合可能会考虑使用。

4、java栈:
也是虚拟机栈。每个虚拟机的线程都有一个私有的栈,一个线程的java栈在线程创建的时候被创建,java栈中保存着局部变量、方法参数、还有java的调用方法和返回值等。

5、本地方法栈:
与java栈很类似,最大不同是本地方法栈用于本地方法调用。java虚拟机允许java直接调用本地方法(通常本地方法为C语言编写)
本地方法栈服务的对象是JVM执行的native方法,而虚拟机栈服务的是JVM执行的java方法。

根据最开始的贴出来的java虚拟机的基本结构图解,如下,我们可以知道
还有垃圾回收系统和PC寄存器。那我们再往下看看。
在这里插入图片描述

垃圾回收系统:
是java的核心,也是必不可少的,java有一套自己进行垃圾清理的机制,
开发者无需手动清理。

PC寄存器:
是每个线程私有的空间,java虚拟机会为每个线程创建PC寄存器,在任意时刻,一个java线程总是在执行一个方法,这个方法被称为当前方法,如果当前方法不是本地方法,PC寄存器就会执行当前正在被执行的指令,如果是本地方法,则PC寄存器的值为undefined。寄存器存放如当前执行环境指针、程序计数器、操作栈指针、计算的变量指针等信息。


最后看一下运行时数据区的图解

图片来自网络
在这里插入图片描述

java虚拟机栈和本地方法栈的区别

什么是java虚拟机栈

虚拟机栈是用于描述java方法执行的内存模型。
Java虚拟机栈是线程私有的, 生命周期与线程相同. 虚拟机栈存放栈帧, 栈帧用于存储局部变量表, 部分结果值, 方法的初始化参数和返回信息, 方法的执行通过栈帧的压栈和出栈实现.

什么是本地方法栈

本地方法栈的功能和特点类似于虚拟机栈,均具有线程隔离的特点以及都能抛出StackOverflowError和OutOfMemoryError异常。
  不同的是,本地方法栈服务的对象是JVM执行的native方法,而虚拟机栈服务的是JVM执行的java方法。

共享问题

方法区和堆由所有线程共享
1、堆:存放所有程序在运行时创建的对象
2、方法区:当JVM的类装载器加载.class文件,并进行解析,把解析的类型信息放入方法区。

Java栈和PC寄存器由线程独享
1、JVM栈是线程私有的,每个线程创建的同时都会创建JVM栈,JVM栈中存放的为当前线程中局部基本类型的变量(java中定义的八种基本类型:boolean、char、byte、short、int、long、float、double)、部分的返回结果以及Stack Frame,非基本类型的对象在JVM栈上仅存放一个指向堆上的地址
2、本地方法栈:存储本地方法调用的状态


JVM垃圾回收

Sun的JVMGenerationalCollecting(垃圾回收)原理是这样的:
把对象分为年轻代(Young)、年老代(Tenured)、持久代(Perm),对不同生命周期的对象使用不同的算法。(基于对对象生命周期分析)

Young(年轻代)
年轻代分三个区。一个Eden(伊甸园)区,两个Survivor(幸存)区。
大部分对象在Eden区中生成。
当Eden区满时,还存活的对象将被复制到Survivor区(两个中的一个),
当这个Survivor区满时,此区的存活对象将被复制到另外一个Survivor区,
当这个Survivor也满了的时候,从第一个Survivor区复制过来的并且此时还存活的对象,将被复制年老区(Tenured。需要注意,Survivor的两个区是对称的,没先后关系,所以同一个区中可能同时存在从Eden复制过来对象,和从前一个Survivor复制过来的对象,而复制到年老区的只有从第一个Survivor去过来的对象。而且,Survivor区总有一个是空的。)

Tenured(年老代)
年老代存放从年轻代存活的对象。一般来说年老代存放的都是生命期较长的对象。

Perm(持久代)
用于存放静态文件,如今Java类、方法等。持久代对垃圾回收没有显著影响,但是有些应用可能动态生成或者调用一些class,例如Hibernate等,在这种时候需要设置一个比较大的持久代空间来存放这些运行过程中新增的类。持久代大小通过-XX:MaxPermSize=进行设置。

注意:
JDK8 HotSpot JVM 将移除永久区,使用本地内存来存储类元数据信息并称之为:元空间(Metaspace)。

元空间的本质和永久代类似,都是对JVM规范中方法区的实现。不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制。

  -XX:MetaspaceSize:
  初始空间大小,达到该值就会触发垃圾收集进行类型卸载,
  同时GC会对该值进行调整:如果释放了大量的空间,就适当降低该值;
  如果释放了很少的空间,那么在不超过MaxMetaspaceSize时,适当提高该值。
  
  -XX:MaxMetaspaceSize:
  最大空间,默认是没有限制的。

 除了上面两个指定大小的选项以外,还有两个与 GC 相关的属性:
  -XX:MinMetaspaceFreeRatio:
  在GC之后,最小的Metaspace剩余空间容量的百分比,减少为分配空间所导致的垃圾收集
  
  -XX:MaxMetaspaceFreeRatio:
  在GC之后,最大的Metaspace剩余空间容量的百分比,减少为释放空间所导致的垃圾收集

为什么1.8要移除永久区,改为元空间??

  • 字符串存在永久代中,现实使用中易出问题, 由于永久代内存经常不够用或发生内存泄露,爆出异常 java.lang.OutOfMemoryError: PermGen

  • 类及方法的信息等比较难确定其大小,因此对于永久代的大小指定比较困难,太小容易出现永久代溢出,太大则容易导致老年代溢出。

  • 永久代会为 GC 带来不必要的复杂度,并且回收效率偏低。


JVM中GC什么时候开始进行

GC 经常发生的区域是堆区,堆区还可以细分为新生代、老年代,新生代还分为一个 Eden 区和两个 Survivor 区

“你能不能谈谈,java GC是在什么时候,对什么东西,做了什么事情?”

在什么时候:

1.新生代有一个Eden区和两个survivor区,首先将对象放入Eden区,如果空间不足就向其中的一个survivor区上放,如果仍然放不下就会引发一次发生在新生代的minor GC,将存活的对象放入另一个survivor区中,然后清空Eden和之前的那个survivor区的内存。在某次GC过程中,如果发现仍然又放不下的对象,就将这些对象放入老年代内存里去。

2.大对象以及长期存活的对象直接进入老年区。

3.当每次执行minor GC的时候应该对要晋升到老年代的对象进行分析,如果这些马上要到老年区的老年对象的大小超过了老年区的剩余大小,那么执行一次Full GC以尽可能地获得老年区的空间。

对什么东西:
从GC Roots搜索不到,而且经过一次标记清理之后仍没有复活的对象。

做什么:
新生代:复制清理;
老年代:标记-清除和标记-压缩算法;
永久代:存放Java中的类和加载类的类加载器本身。

垃圾回收算法有哪些??
1,引用计数 :原理是此对象有一个引用,即增加一个计数,删除一个引用则减少一个计数。垃圾回收时,只用收集计数为 0 的对象。此算法最致命的是无法处理循环引用的问题;

2,标记-清除 :此算法执行分两阶段。第一阶段从引用根节点开始标记所有被引用的对象,第二阶段遍历整个堆,把未标记的对象清除;

此算法需要暂停整个应用,同时,会产生内存碎片;

3,复制算法 :此算法把内存空间划为两个相等的区域,每次只使用其中一个区域。垃圾回收时,遍历当前使用区域,把正在使用中的对象复制到另外一个区域中;

此算法每次只处理正在使用中的对象,因此复制成本比较小,同时复制过去以后还能进行相应的内存整理,不会出现 “碎片” 问题。当然,此算法的缺点也是很明显的,就是需要两倍内存空间;

4,标记-整理 :此算法结合了 “标记-清除” 和 “复制” 两个算法的优点。也是分两阶段,第一阶段从根节点开始标记所有被引用对象,第二阶段遍历整个堆,把清除未标记对象并且把存活对象 “压缩” 到堆的其中一块,按顺序排放。

此算法避免了 “标记-清除” 的碎片问题,同时也避免了 “复制” 算法的空间问题。

感谢以下博客~

https://blog.csdn.net/iG_xdd/article/details/79748230
https://blog.csdn.net/gao_sl/article/details/80317911
https://blog.csdn.net/qq_34872215/article/details/79660141
https://www.cnblogs.com/manayi/p/9293302.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值