Java 虚拟机实战

本贴最后更新于 3185 天前,其中的信息可能已经时移世异

虚拟机实战

  1. Java 堆溢出
    1. Java 堆用于存储对象实例,只要不断创建对象,并且保证 GC Roots 到对象之间有可达路径来避免垃圾回收机制清除这些对象,那么在对象数量达到最大堆的容量限制后就会产生内存溢出异常。
  • 代码示例:Java 堆内存溢出异常测试
import java.util.List; import java.util.ArrayList; /** * VM Args: -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError */ public class HeapOOM{ static class OOMObject{ } public static void main(String[] args){ List<OOMObject> list = new ArrayList<OOMObject>(); while(true){ list.add(new OOMObject()); } } }
  • 结果演示:
    运行环境为:
james@james:~ > java -version java version "1.8.0_101" Java(TM) SE Runtime Environment (build 1.8.0_101-b13) Java HotSpot(TM) 64-Bit Server VM (build 25.101-b13, mixed mode) james@james:~/code/hello-world/code/JVM > java -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError HeapOOM java.lang.OutOfMemoryError: Java heap space Dumping heap to java_pid86289.hprof ... Heap dump file created [27533560 bytes in 0.115 secs] Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at java.util.Arrays.copyOf(Arrays.java:3210) at java.util.Arrays.copyOf(Arrays.java:3181) at java.util.ArrayList.grow(ArrayList.java:261) at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:235) at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:227) at java.util.ArrayList.add(ArrayList.java:458) at HeapOOM.main(HeapOOM.java:13)
  • 结果分析:
    1. 虚拟机堆转储快照分析工具 jhat
    2. jhat(JVM Heap Analysis Tool)是 Sun JDK 提供的分析工具,可以在浏览器中查看分析结果。
    3. 分析结果默认是以包为单位进行分组显示,分析内存泄露问题主要会使用到其中的“Heap Histogram(堆直方图)”与 QQL 页签的功能。前者可以找到内存中总容量最大的对象和实例数最多的对象,后者是标准的对象查询语言。
    4. 由于加载 dump 快照文件需要比 dump 文件更大的内存,所以一般在 64 位 JDK,大内存服务器上进行。
james@james:~/code/hello-world/code/JVM > jhat java_pid86289.hprof Reading from java_pid86289.hprof... Dump file created Tue Jan 17 10:01:43 CST 2017 Snapshot read, resolving... Resolving 814423 objects... Chasing references, expect 162 dots.................................................................................................................................................................. Eliminating duplicate references.................................................................................................................................................................. Snapshot resolved. Started HTTP server on port 7000 Server is ready.

image

  • 如上图可以看出对象 HeapOOM 的实例数最多,但是它的空间是 0,占用空间最大的是 Object。原因现在还不好说
  1. 虚拟机栈和本地方法栈溢出
    1. 由于在 HotSpot 虚拟机中并不区分虚拟机栈和本地方法栈,因此对 HotSpot 来说设置本地方法栈大小的参数-Xoss 是无效的,栈容量只由-Xss 参数决定。
    2. 关于虚拟机栈和本地方法栈,在 Java 虚拟机规范中描述了两种异常:
      1. 如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出 StackOverflowError 异常;
      2. 如果虚拟机在扩展栈时无法申请到足够的内存空间,则抛出 OutOfMemoryError 异常。
    3. 实际实现可能与规范有所差异。
  • 代码示例:虚拟机栈和本地方法栈 OOM 测试
/** * VM Args: -Xss 128k */ public class JavaVMStackSOF{ private int stackLength = 1; public void stackLeak(){ stackLength++; stackLeak(); } public static void main(String[] args) throws Throwable{ JavaVMStackSOF oom = new JavaVMStackSOF(); try{ oom.stackLeak(); }catch(Throwable e){ System.out.println("stack length:"+oom.stackLength); throw e; } } }
  • 运行结果:
james@james:~/code/hello-world/code/JVM > java -Xss128k JavaVMStackSOF The stack size specified is too small, Specify at least 228k Error: Could not create the Java Virtual Machine. Error: A fatal exception has occurred. Program will exit. james@james:~/code/hello-world/code/JVM > java -Xss228k JavaVMStackSOF stack length:1550 Exception in thread "main" java.lang.StackOverflowError at JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:9) at JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:9) at JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:9) at JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:9)
  • 结果分析:
    1. 在单个线程下,无论是由于栈帧太大还是虚拟机栈容量太小,当内存无法分配的时候,虚拟机抛出的都是 StackOverflowError 异常。
    2. 如果测试时不限于单线程,通过不断地建立线程的方式倒是可以产生内存溢出异常,如下所示。但是这样产生的内存溢出异常与栈空间是否足够大并不存在任何联系,或者准确地说,在这种情况下,为每个线程的栈分配的内存越大,反而越容易出现内存溢出异常。
  • 代码示例:创建线程导致内存溢出异常
public class JavaVMStackOOM{ private void dontStop(){ while(true){ System.out.println("dontStop"); } } public void stackLeakByThread(){ while(true){ Thread thread = new Thread(new Runnable(){ @Override public void run(){ dontStop(); } }); thread.start(); } } public static void main(String[] args){ JavaVMStackOOM oom = new JavaVMStackOOM(); oom.stackLeakByThread(); } }
  • 结果分析:
    上面的代码通过不断创建线程来实现虚拟机栈和本地方法栈溢出,但是在 linux 下并没有抛出异常,而是 cpu 使用率超高的状态,内存使用也不断增大。只能通过 kill 命令杀死进程。
  • jps:虚拟机进程状况工具,类似 ps 命令;
  • jstat:虚拟机统计信息监视工具,它可以显示本地或者远程虚拟机进程中的类装载、内存、垃圾收集、JIT 编译等运行数据。
  • JVM

    JVM(Java Virtual Machine)Java 虚拟机是一个微型操作系统,有自己的硬件构架体系,还有相应的指令系统。能够识别 Java 独特的 .class 文件(字节码),能够将这些文件中的信息读取出来,使得 Java 程序只需要生成 Java 虚拟机上的字节码后就能在不同操作系统平台上进行运行。

    180 引用 • 120 回帖 • 6 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • james

    怎么到这儿啦?

推荐标签 标签

  • HBase

    HBase 是一个分布式的、面向列的开源数据库,该技术来源于 Fay Chang 所撰写的 Google 论文 “Bigtable:一个结构化数据的分布式存储系统”。就像 Bigtable 利用了 Google 文件系统所提供的分布式数据存储一样,HBase 在 Hadoop 之上提供了类似于 Bigtable 的能力。

    17 引用 • 6 回帖 • 69 关注
  • 机器学习

    机器学习(Machine Learning)是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。专门研究计算机怎样模拟或实现人类的学习行为,以获取新的知识或技能,重新组织已有的知识结构使之不断改善自身的性能。

    77 引用 • 37 回帖
  • WiFiDog

    WiFiDog 是一套开源的无线热点认证管理工具,主要功能包括:位置相关的内容递送;用户认证和授权;集中式网络监控。

    1 引用 • 7 回帖 • 621 关注
  • Laravel

    Laravel 是一套简洁、优雅的 PHP Web 开发框架。它采用 MVC 设计,是一款崇尚开发效率的全栈框架。

    19 引用 • 23 回帖 • 750 关注
  • Outlook
    1 引用 • 5 回帖 • 2 关注
  • Love2D

    Love2D 是一个开源的, 跨平台的 2D 游戏引擎。使用纯 Lua 脚本来进行游戏开发。目前支持的平台有 Windows, Mac OS X, Linux, Android 和 iOS。

    14 引用 • 53 回帖 • 563 关注
  • Docker

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的操作系统上。容器完全使用沙箱机制,几乎没有性能开销,可以很容易地在机器和数据中心中运行。

    498 引用 • 934 回帖
  • RIP

    愿逝者安息!

    8 引用 • 92 回帖 • 422 关注
  • DevOps

    DevOps(Development 和 Operations 的组合词)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合。

    59 引用 • 25 回帖
  • Node.js

    Node.js 是一个基于 Chrome JavaScript 运行时建立的平台, 用于方便地搭建响应速度快、易于扩展的网络应用。Node.js 使用事件驱动, 非阻塞 I/O 模型而得以轻量和高效。

    139 引用 • 269 回帖 • 1 关注
  • 百度

    百度(Nasdaq:BIDU)是全球最大的中文搜索引擎、最大的中文网站。2000 年 1 月由李彦宏创立于北京中关村,致力于向人们提供“简单,可依赖”的信息获取方式。“百度”二字源于中国宋朝词人辛弃疾的《青玉案·元夕》词句“众里寻他千百度”,象征着百度对中文信息检索技术的执著追求。

    63 引用 • 785 回帖 • 57 关注
  • Postman

    Postman 是一款简单好用的 HTTP API 调试工具。

    4 引用 • 3 回帖
  • 房星科技

    房星网,我们不和没有钱的程序员谈理想,我们要让程序员又有理想又有钱。我们有雄厚的房地产行业线下资源,遍布昆明全城的 100 家门店、四千地产经纪人是我们坚实的后盾。

    6 引用 • 141 回帖 • 621 关注
  • MySQL

    MySQL 是一个关系型数据库管理系统,由瑞典 MySQL AB 公司开发,目前属于 Oracle 公司。MySQL 是最流行的关系型数据库管理系统之一。

    695 引用 • 537 回帖
  • ngrok

    ngrok 是一个反向代理,通过在公共的端点和本地运行的 Web 服务器之间建立一个安全的通道。

    7 引用 • 63 回帖 • 661 关注
  • 深度学习

    深度学习(Deep Learning)是机器学习的分支,是一种试图使用包含复杂结构或由多重非线性变换构成的多个处理层对数据进行高层抽象的算法。

    45 引用 • 44 回帖
  • jQuery

    jQuery 是一套跨浏览器的 JavaScript 库,强化 HTML 与 JavaScript 之间的操作。由 John Resig 在 2006 年 1 月的 BarCamp NYC 上释出第一个版本。全球约有 28% 的网站使用 jQuery,是非常受欢迎的 JavaScript 库。

    63 引用 • 134 回帖 • 735 关注
  • abitmean

    有点意思就行了

    41 关注
  • 印象笔记
    3 引用 • 21 回帖
  • Electron

    Electron 基于 Chromium 和 Node.js,让你可以使用 HTML、CSS 和 JavaScript 构建应用。它是一个由 GitHub 及众多贡献者组成的活跃社区共同维护的开源项目,兼容 Mac、Windows 和 Linux,它构建的应用可在这三个操作系统上面运行。

    16 引用 • 143 回帖 • 3 关注
  • 尊园地产

    昆明尊园房地产经纪有限公司,即:Kunming Zunyuan Property Agency Company Limited(简称“尊园地产”)于 2007 年 6 月开始筹备,2007 年 8 月 18 日正式成立,注册资本 200 万元,公司性质为股份经纪有限公司,主营业务为:代租、代售、代办产权过户、办理银行按揭、担保、抵押、评估等。

    1 引用 • 22 回帖 • 822 关注
  • Q&A

    提问之前请先看《提问的智慧》,好的问题比好的答案更有价值。

    10662 引用 • 48476 回帖 • 65 关注
  • Word
    13 引用 • 41 回帖 • 1 关注
  • InfluxDB

    InfluxDB 是一个开源的没有外部依赖的时间序列数据库。适用于记录度量,事件及实时分析。

    2 引用 • 114 关注
  • Tomcat

    Tomcat 最早是由 Sun Microsystems 开发的一个 Servlet 容器,在 1999 年被捐献给 ASF(Apache Software Foundation),隶属于 Jakarta 项目,现在已经独立为一个顶级项目。Tomcat 主要实现了 JavaEE 中的 Servlet、JSP 规范,同时也提供 HTTP 服务,是市场上非常流行的 Java Web 容器。

    162 引用 • 529 回帖 • 7 关注
  • uTools

    uTools 是一个极简、插件化、跨平台的现代桌面软件。通过自由选配丰富的插件,打造你得心应手的工具集合。

    8 引用 • 37 回帖 • 1 关注
  • 导航

    各种网址链接、内容导航。

    45 引用 • 177 回帖