虚拟机介绍

Java虚拟机(JVM)一种用于计算机设备的规范,可用不同的方式(软件或硬件)加以实现。编译虚拟机的指令集与编译微处理器的指令集非常类似。Java虚拟机包括一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个存储方法域。
Java虚拟机(JVM)是可运行Java代码的假想计算机。只要根据JVM规格描述将解释器移植到特定的计算机上,就能保证经过编译的任何Java代码能够在该系统上运行。
Java虚拟机是一个想象中的机器,在实际的计算机上通过软件模拟来实现。Java虚拟机有自己想象中的硬件,如处理器、堆栈、寄存器等,还具有相应的指令系统。
Java虚拟机规范定义了一个抽象的——而非实际的——机器或处理器。这个规范描述了一个指令集,一组寄存器,一个堆栈,一个“垃圾堆”,和一个方法区。一旦一个Java虚拟机在给定的平台上运行,任何Java程序(编译之后的程序,称作字节码)都能在这个平台上运行。Java虚拟机(JVM)可以以一次一条指令的方式来解释字节码(把它映射到实际的处理器指令),或者字节码也可以由实际处理器中称作just-in-time的编译器进行进一步的编译。

如何有效的内存管理,JVM垃圾回收机制

标记垃圾的算法

引用计数法

引用计数法就是给对象中添加一个引用计数器,每当有一个地方引用它,计数器就加 1;当引用失效,计数器就减 1;任何时候计数器为 0 的对象就是不可能再被使用的,可以当做垃圾收集。这种方法实现起来很简单而且优缺点都很明显。

优点 执行效率高,程序执行受影响较小
缺点 无法检测出循环引用的情况,导致内存泄露

可达性分析算法

这个算法的基本思想就是通过一系列的称为 “GC Roots” 的对象作为起点,从这些节点开始向下搜索,节点所走过的路径称为引用链,当一个对象到 GC Roots 没有任何引用链相连的话,则证明此对象是不可用的。
那么什么对象可以作为GCRoot?

  • 虚拟机栈中的引用对象
  • 方法区中的常量引用对象
  • 方法区中的类静态属性引用对象
  • 本地方法栈中的引用对象
  • 活跃线程中的引用对象

    在可达性分析法中不可达的对象,它们暂时处于“缓刑阶段”,要真正宣告一个对象死亡,至少要经历两次标记过程;可达性分析法中不可达的对象被第一次标记并且进行一次筛选,筛选的条件是此对象是否有必要执行 finalize 方法。当对象没有覆盖 finalize 方法,或 finalize 方法已经被虚拟机调用过时,虚拟机将这两种情况视为没有必要执行。被判定为需要执行的对象将会被放在一个队列中进行第二次标记,除非这个对象与引用链上的任何一个对象建立关联,否则就会被真的回收。

垃圾回收算法

标记清除算法

该算法分为“标记”和“清除”两个阶段:标记阶段的任务是标记出所有需要被回收的对象,清除阶段就是回收被标记的对象所占用的空间。它是最基础的收集算法,效率也很高,但是会带来两个明显的问题:

  • 效率问题
  • 空间问题(标记清除后会产生大量不连续的碎片)

复制算法

为了解决效率问题,我们开发出了复制算法。它可以将内存分为大小相同的两块,每次使用其中的一块。当第一块的内存使用完后,就将还存活的对象复制到另一块去,然后再把使用的空间一次清理掉。这样就使每次的内存回收都是对内存区间的一半进行回收。

简单来说就是该对象分为对象面以及空闲面,对象在对象面上创建,对象面上存活的对象会被复制到空闲面,接下来就可以清除对象面的内存。

这种算法的优缺点也比较明显

**优点:**解决碎片化问题,顺序分配内存简单高效

**缺点:**只适用于存活率低的场景,如果极端情况下如果对象面上的对象全部存活,就要浪费一半的存储空间。

标记整理算法

为了解决复制算法的缺陷,充分利用内存空间,提出了标记整理算法。该算法标记阶段和标记清除一样,但是在完成标记之后,它不是直接清理可回收对象,而是将存活对象都向一端移动,然后清理掉端边界以外的内存。

分代收集算法

当前虚拟机的垃圾收集都采用分代收集算法,这种算法就是根据具体的情况选择具体的垃圾回收算法。一般将 java 堆分为新生代和老年代,这样我们就可以根据各个年代的特点选择合适的垃圾收集算法。

比如在新生代中,每次收集都会有大量对象死去,所以可以选择复制算法,只需要付出少量对象的复制成本就可以完成每次垃圾收集。而老年代的对象存活几率是比较高的,而且没有额外的空间对它进行分配担保,所以我们必须选择“标记-清除”或“标记-整理”算法进行垃圾收集。

Java虚拟机运行时数据区

方法区:

方法区在JDK1.8之后把名字改成了“Metaspace",可以翻译成"元数据空间",这是一块线程共享的内存空间,主要用于存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。

Java虚拟机规范将方法区描述为堆的一个逻辑部分,但它有一个别名”Non-Heap 非堆“ 用于与Java堆区分。

很多人愿意把方法区成为”永久代“,本质上两者并不等价。HotSpot虚拟机 团队选择把GC分代收集扩展至方法区,或者说使用永久带实现方法区而已。

方法区存在的问题:

永久代容易遇到内存溢出问题(HotSpot永久代有-XX:MaxPermSize上限)
当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常
运行时常量池也是方法区的一个部分,主要用于存放编译器生成的各种字面量和符号引用。类加载后会进入方法区的运行时常量池

运行时常量池存在的问题:

当常量池无法再申请到内存空间时会抛出OutOfMemoryError异常

虚拟机栈

虚拟机栈是线程私有的内存空间,其生命周期与线程相同,是用于Java方法执行的内存模型。方法执行时会创建栈帧,用于存储局部变量表,操作数栈,动态链接,方法出口等。

虚拟机栈存在的问题:

线程请求的栈深度大于虚拟机所允许的深度,抛出StackOverflowError异常
虚拟机栈动态扩展时无法申请到足够的内存,抛出OutOfMemoryError异常

本地方法栈

其发挥的作用和存在的问题与Java虚拟机栈类似,这里主要说一下其区别。其区别主要是虚拟机栈为虚拟机执行Java方法服务,而本地方法栈为虚拟机使用到Native方法服务。

知识点:Hotspot虚拟机中将本地方法栈与虚拟机栈合二为一。

Java堆

Java堆是虚拟机中占内存最大的一块内存空间,是所有线程共享的内存区域,当虚拟机启动的时候就会创建。它的作用主要是存放对象实例,几乎所有的对象实例都在这里分配内存。我们来看下Java虚拟机规范是怎么描述它的:

所有的对象实例以及数组都要在堆上分配,但是随着JIT编译器的发展与逃逸分析技术逐渐成熟,栈上分配、标量替换优化技术将会导致一些微妙的变化发生,所有的对象都分配到堆上也渐渐变得不是那么”绝对“了。

这一块内存空间也是垃圾收集器管理的主要区域,所以有时候也被称为”GC堆“。

Java堆存在的问题:

如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常。

程序计数器

程序计数器是线程私有的一块占用较小的内存空间,主要用于记录当前线程执行到哪里了。而且这也是唯一一个没有内存溢出的区域。

直接内存

除了以上几块内存空间外,还有一块内存空间就是直接内存,它不属于运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域,但是这部分频繁使用也可能导致OutOfMemoryError异常。NIO可以使用Native函数库直接分配堆外内存空间。

虚拟机如何配置

1、-Xmixed mixed mode execution (default)
混合模式执行

2、-Xint interpreted mode execution only
解释模式执行

3、-Xbootclasspath:<directories and zip/jar files separated by ;>
set search path for bootstrap classes and resources
设置zip/jar资源或者类(.class文件)存放目录路径

3、-Xbootclasspath/a:<directories and zip/jar files separated by ;>
append to end of bootstrap class path
追加zip/jar资源或者类(.class文件)存放目录路径

4、-Xbootclasspath/p:<directories and zip/jar files separated by ;>
prepend in front of bootstrap class path
预先加载zip/jar资源或者类(.class文件)存放目录路径

5、-Xnoclassgc disable class garbage collection
关闭类垃圾回收功能

6、-Xincgc enable incremental garbage collection
开启类的垃圾回收功能

7、-Xloggc: log GC status to a file with time stamps
记录垃圾回日志到一个文件。

8、-Xbatch disable background compilation
关闭后台编译

9、-Xms set initial Java heap size
设置JVM初始化堆内存大小

10、-Xmx set maximum Java heap size
设置JVM最大的堆内存大小

11、-Xss set java thread stack size
设置JVM栈内存大小

12、-Xprof output cpu profiling data
输入CPU概要表数据

13、-Xfuture enable strictest checks, anticipating future default
执行严格的代码检查,预测可能出现的情况

14、-Xrs reduce use of OS signals by Java/VM (see documentation)
通过JVM还原操作系统信号

15、-Xcheck:jni perform additional checks for JNI functions
对JNI函数执行检查

16、-Xshare:off do not attempt to use shared class data
尽可能不去使用共享类的数据

17、-Xshare:auto use shared class data if possible (default)
尽可能的使用共享类的数据

18、-Xshare:on require using shared class data, otherwise fail.
尽可能的使用共享类的数据,否则运行失败

一篇文章了解Java虚拟机,Java虚拟机内存详解相关推荐

  1. 一篇文章带你了解-selenium工作原理详解

    前言 Selenium是一个用于Web应用程序自动化测试工具.Selenium测试直接运行在浏览器中,就像真正的用户在操作一样.支持的浏览器包括IE(7, 8, 9, 10, 11),Mozilla ...

  2. 一篇文章让你从JAVA零基础入门`OOP`编程12.19

    一篇文章让你从JAVA零基础入门OOP编程 前言: 此文为玄子,复习ACCP-S1课程后,整理的文章,文中对知识点的解释仅为个人理解. 配套PPT,站点源码,等学习资料 一.预科 1.1 JAVA 介 ...

  3. 一篇文章让你从JAVA零基础入门`OOP`编程12.20

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(QQ_3336392096.png)] 一篇文章让你从JAVA零基础入门OOP编程 前言: 此文为玄子,复习ACCP-S1课程后, ...

  4. 一期完结《一篇文章让你从JAVA零基础入门`OOP`编程》12.21

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(QQ_3336392096.jpg)] 一篇文章让你从JAVA零基础入门OOP编程 前言: 此文为玄子,复习ACCP-S1课程后, ...

  5. [java] 虚拟机(JVM)底层结构详解[转]

    [java] 虚拟机(JVM)底层结构详解[转] 本文来自:曹胜欢博客专栏.转载请注明出处:http://blog.csdn.net/csh624366188 在以前的博客里面,我们介绍了在java领 ...

  6. Java虚拟机之垃圾回收详解一

    Java虚拟机之垃圾回收详解一 Java技术和JVM(Java虚拟机) 一.Java技术概述: Java是一门编程语言,是一种计算平台,是SUN公司于1995年首次发布.它是Java程序的技术基础,这 ...

  7. Java虚拟机中类加载机制详解

    Java虚拟机中类加载机制详解 1,什么是java类加载机制 **首先在java中,是通过编译来生成.class文件(可能在本地,或者网页下载),java的类加载机制就是 将这些.class文件加载到 ...

  8. c++ socket线程池原理_一篇文章看懂 ThreadLocal 原理,内存泄露,缺点以及线程池复用的值传递问题...

    编辑:业余草来源:https://www.xttblog.com/?p=4946 一篇文章看懂 ThreadLocal 原理,内存泄露,缺点以及线程池复用的值传递问题. ThreadLocal 相信不 ...

  9. Java并发编程最佳实例详解系列

    Java并发编程最佳实例详解系列: Java并发编程(一)线程定义.状态和属性 Java并发编程(一)线程定义.状态和属性 线程是指程序在执行过程中,能够执行程序代码的一个执行单元.在java语言中, ...

  10. 《Java和Android开发实战详解》——1.2节Java基础知识

    本节书摘来自异步社区<Java和Android开发实战详解>一书中的第1章,第1.2节Java基础知识,作者 陈会安,更多章节内容可以访问云栖社区"异步社区"公众号查看 ...

最新文章

  1. 使用自定义色系美化JfreeChart图表
  2. .9-Vue源码之AST(5)
  3. 中毒,重装,杀毒……最近一段时间,很烦的一件事,不断重复……
  4. 华为虚拟服务器lanip地址,2018软考网络工程师《华为基础实验》十九配置路由器为DHCPServer...
  5. oracle中substrb用法,oracle中substr和instr的用法
  6. CSS Reset(css的初始化)
  7. 软件设计方法和设计决策
  8. Codeforces Round #403 (Div. 2, based on Technocup 2017 Finals
  9. Java 开发者靠什么逆风翻盘?
  10. 2M口,电口,光口的区别
  11. win7系统下装ubuntu系统
  12. 串口服务器485转以太网
  13. 红黑联盟十周年 汇编语言系列教程
  14. vue-cli脚手架中使用talkingData埋点的方法
  15. Python爬虫入门教程【7】: 蜂鸟网图片爬取之二
  16. 再介绍一篇最新的Contrastive Self-supervised Learning综述论文
  17. matlab在axis,matlab中axis的用法
  18. 修复Lsp解决不能上网的问题
  19. Android 实现书籍翻页效果----原理篇
  20. 安卓手机ROOT后怎么删除系统自带软件?

热门文章

  1. 流量和延迟减半!挑战分布式数据库 TiDB 跨数据中心难题
  2. javaweb项目Filter过滤器详解
  3. 对求解最大公约数算法的一些思考
  4. 思维导图的使用以及常用的工具
  5. 非常好用的 npx!!!
  6. 一诺仪器面试的心得体会
  7. 学习笔记三(STM32串口程序下载新建工程模板)
  8. A-LOAM源码解析
  9. Python-pandas的fillna()方法-填充空值
  10. 精读《async/await 是把双刃剑》