Java虚拟机

2 篇文章 0 订阅
1 篇文章 0 订阅

Java虚拟机

什么是Java虚拟机?

Java虚拟机是一个可以执行Java字节码的虚拟机进程。Java源文件被编译成字节码文件。java解释器(jvm的一部分)会将其解释成对应平台的机器码执行

什么是平台?

  1. CPU和操作系统的总称。
  2. CPU进行计算和控制计算机系统,所以每种CPU都有自己的指令集
  3. 操作系统:控制程序执行的程序,充当程序和硬件之间的中介

在这里插入图片描述

为什么Java被称作是“平台无关的编程语言”?

Java被设计成允许应用程序可以运行在任意的平台,而不需要程序员为每一个平台单独重写或者是重新编译。Java虚拟机让这个变为可能,因为它知道底层硬件平台的指令长度和其他特性。

在这里插入图片描述

JVM的作用
java的跨平台

java源程序先经过javac编译器编译成二进制的.class字节码文件(java的跨平台指的就是.class字节码文件的跨平台,.class字节码文件是与平台无关的),.class文件再运行在jvm上,java解释器(jvm的一部分)会将其解释成对应平台的机器码执行,所以java所谓的跨平台就是在不同平台上安装了不同的jvm,而在不同的平台上生成的.class文件都是一样的,而.class文件再由对应平台的jvm解释成机器码执行

什么是机器码?

我们知道JAVA是跨平台的,为什么呢?因为他有一个jvm,不论那种硬件,只要你装有jvm,那么他就认识这个JAVA字节码~~~~至于底层的机器码,咱不用管,有jvm搞定,他会把字节码再翻译成所在机器认识的机器码~~~

自动内存管理
什么是自动内存管理机制?

对于java程序员来说,有一点是要比C/C++程序员要方便的,那就是程序在运行时,java程序不需要为每一个对象其编写对应的释放内存的代码,JVM虚拟机将为你在合适的时间去释放内存空间,程序不容易出现内存泄漏和内存溢出问题,这就是JVM的自动内存管理机制。

JVM是怎样启动的

第一步:执行JVM启动器java.exe
第二步:启动器加载jvm.dll,(虚拟机本身)
第三步:加载java核心类库
第四步:最后加载应用程序
在这里插入图片描述

扩展:

  1. .dll是 Dynaic Link library动态链接库,一般C语言开发出来的
  2. Eclipse和Tomcat启动时都会启动一个JVM
JVM内部的JIT解释器

JIT是为了补强虚拟机边运行边解释的低性能。它会智能地对热点代码进行优化且重复利用。从策略的角度来讲,就是通过查表或者缓存,而不是重复解决子问题,这样大大缩短解决问题的时间。

JVM运行时的数据区域

jvm在执行Java程序的过程中会把它所管理的内存划分为5个不同的数据区域。5区域存储不同类型的数据,5区域的内存分配和销毁的时间也不同,有的区域随着虚拟机进程的启动而存在,有些区域则是依赖用户线程的启动和结束而建立和销毁。

分为线程共享的区域和线程独有的区域

线程共享的区域:方法区,堆

线程独有的区域:程序计数器,虚拟机栈,本地方法栈在这里插入图片描述
方法区:
用来存储JVM加载的类信息、常量、静态变量、方法信息,字段信息,类型信息即时编译器编译后的代码等数据。虽然Java虚拟机规范把方法区描述为堆的一个逻辑部分,但是为了和堆区分开来,它也叫Non-Heap(非堆)。方法区无法满足内存分配需求时,报OutOfMemoryError异常。

堆:
JVM所管理的内存中最大的一块,也是GC管理的主要区域。理论上所有的对象实例和数组都要在堆上分配。堆的大小是可以扩展的,通过-Xms和-Xms控制,并且堆无法扩展的时候就会报OutOfMemoryError异常。

虚拟机栈:
每个方法在执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。
Java虚拟机栈有两种异常情况:OutOfMemoryError(扩展时无法申请到足够内存)和StackOverflowError(线程请求的栈深度大于虚拟机所允许的深度)。
程序计数器:
程序计数器是一块较小的空间,它可以看作是当前线程所执行的字节码文件的行号指令器。在虚拟机的概念里,字节码解释器工作时就是通过改变这个计数器来选取下一条需要执行的字节码指令,分支,循环,跳转,异常处理都需要依赖这个计数器来完成。
由于java虚拟机的多线程是由线程轮流切换执行时间来实现的,一个处理器在某一段时间都执行一条线程中的指令,因此为了切换执行后恢复到正确的位置,每条线程都需要一个独立的计数器,各个线程互不影响,这类内存区域为线程私有的内存。
本地方法栈:
同Java虚拟机栈类似,只不过Java虚拟机栈为虚拟机执行Java方法服务,本地方法栈为虚拟机使用Native方法服务。HotSpot直接将两个栈合二为一。也规定了两种异常:OutOfMemoryError和StackOverflowError。

JVM对象“已死”的判定算法

有两种算法可以判定对象是否存活:
引用计数算法:
给对象中添加一个引用计数器,每当一个地方应用了对象,计数器加1;当引用失效,计数器减1;当计数器为0表示该对象已死、可回收。但是它很难解决两个对象之间相互循环引用的情况。
根搜索算法:
通过一系列称为“GC Roots”的对象作为起点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连(即对象到GC Roots不可达),则证明此对象已死、可回收。Java中可以作为GC Roots的对象包括:虚拟机栈中引用的对象、本地方法栈中Native方法引用的对象、方法区静态属性引用的对象、方法区常量引用的对象。

JVM垃圾收集算法

1.标记-清除算法
最基础的算法,分标记和清除两个阶段:首先标记处所需要回收的对象,在标记完成后统一回收所有被标记的对象。
它有两点不足:
一个效率问题,标记和清除过程都效率不高;
一个是空间问题,标记清除之后会产生大量不连续的内存碎片空间碎片太多导致需要分配大对象时无法找到足够的连续内存而不得不提前触发另一次垃圾回收动作。
在这里插入图片描述
2.分段复制算法:
为了解决效率问题他将可用内存按容量划分为大小相等的两块,每次只需要使用其中一块。当一块内存用完了,将还存活的对象复制到另一块上面,然后再把刚刚用完的内存空间一次清理掉。这样就解决了内存碎片问题,这样可能会造成卡顿代价也很大。
在这里插入图片描述
3.标记-整理算法:
复制算法在对象存活率较高时就会进行频繁的复制操作,效率将降低。因此又有了标记-整理算法,标记过程同标记-清除算法,但是在后续步骤不是直接对对象进行清理,而是让所有存活的对象都向一侧移动,然后直接清理掉端边界以外的内存。
在这里插入图片描述
4.分代收集算法:
当前商业虚拟机的GC都是采用分代收集算法,这种算法并没有什么新的思想,而是根据对象存活周期的不同将堆分为:新生代和老年代,方法区称为永久代(在新的版本中已经将永久代废弃,引入了元空间的概念,永久代使用的是JVM内存而元空间直接使用物理内存

新生代:
新生代中的对象“朝生夕死”,每次GC时都会有大量对象死去,少量存活,使用复制算法
新产生的对象优先进去Eden区,当Eden区满了之后再使用Survivor from,当Survivor from 也满了之后就进行Minor GC(新生代GC),将Eden和Survivor from中存活的对象copy进入Survivor to,然后清空Eden和Survivor from,这个时候原来的Survivor from成了新的Survivor to,原来的Survivor to成了新的Survivor from。复制的时候,如果Survivor to 无法容纳全部存活的对象,则根据老年代的分配担保(类似于银行的贷款担保)将对象copy进去老年代,如果老年代也无法容纳,则进行Full GC(老年代GC)。

老年代:
老年代中的对象因为对象存活率高、没有额外空间进行分配担保,就使用标记-清除或标记-整理算法。
大对象直接进入老年代:JVM中有个参数配置-XX:PretenureSizeThreshold,令大于这个设置值的对象直接进入老年代,目的是为了避免在Eden和Survivor区之间发生大量的内存复制。
长期存活的对象进入老年代:JVM给每个对象定义一个对象年龄计数器,如果对象在Eden出生并经过第一次Minor GC后仍然存活,并且能被Survivor容纳,将被移入Survivor并且年龄设定为1。没熬过一次Minor GC,年龄就加1,当他的年龄到一定程度(默认为15岁,可以通过XX:MaxTenuringThreshold来设定),就会移入老年代。
在这里插入图片描述
点击查看------String,StringBuilder,StringBuffer的区别

点击查看------Oracle基础知识

点击查看------Oracle 表空间,序列,索引,分区表的应用

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值