Java 虚拟机实战

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

虚拟机实战

  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 回帖 • 1 关注

相关帖子

欢迎来到这里!

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

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

    怎么到这儿啦?

推荐标签 标签

  • 支付宝

    支付宝是全球领先的独立第三方支付平台,致力于为广大用户提供安全快速的电子支付/网上支付/安全支付/手机支付体验,及转账收款/水电煤缴费/信用卡还款/AA 收款等生活服务应用。

    29 引用 • 347 回帖
  • Excel
    31 引用 • 28 回帖 • 1 关注
  • SMTP

    SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式。SMTP 协议属于 TCP/IP 协议簇,它帮助每台计算机在发送或中转信件时找到下一个目的地。

    4 引用 • 18 回帖 • 636 关注
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3194 引用 • 8214 回帖 • 1 关注
  • 京东

    京东是中国最大的自营式电商企业,2015 年第一季度在中国自营式 B2C 电商市场的占有率为 56.3%。2014 年 5 月,京东在美国纳斯达克证券交易所正式挂牌上市(股票代码:JD),是中国第一个成功赴美上市的大型综合型电商平台,与腾讯、百度等中国互联网巨头共同跻身全球前十大互联网公司排行榜。

    14 引用 • 102 回帖 • 319 关注
  • CodeMirror
    1 引用 • 2 回帖 • 154 关注
  • ngrok

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

    7 引用 • 63 回帖 • 647 关注
  • 小说

    小说是以刻画人物形象为中心,通过完整的故事情节和环境描写来反映社会生活的文学体裁。

    31 引用 • 108 回帖
  • 大数据

    大数据(big data)是指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合,是需要新处理模式才能具有更强的决策力、洞察发现力和流程优化能力的海量、高增长率和多样化的信息资产。

    93 引用 • 113 回帖
  • OAuth

    OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是 oAuth 的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此 oAuth 是安全的。oAuth 是 Open Authorization 的简写。

    36 引用 • 103 回帖 • 27 关注
  • Vim

    Vim 是类 UNIX 系统文本编辑器 Vi 的加强版本,加入了更多特性来帮助编辑源代码。Vim 的部分增强功能包括文件比较(vimdiff)、语法高亮、全面的帮助系统、本地脚本(Vimscript)和便于选择的可视化模式。

    29 引用 • 66 回帖 • 3 关注
  • OpenCV
    15 引用 • 36 回帖 • 1 关注
  • 区块链

    区块链是分布式数据存储、点对点传输、共识机制、加密算法等计算机技术的新型应用模式。所谓共识机制是区块链系统中实现不同节点之间建立信任、获取权益的数学算法 。

    92 引用 • 752 回帖 • 1 关注
  • OneDrive
    2 引用 • 2 关注
  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    24718 引用 • 101513 回帖
  • PWA

    PWA(Progressive Web App)是 Google 在 2015 年提出、2016 年 6 月开始推广的项目。它结合了一系列现代 Web 技术,在网页应用中实现和原生应用相近的用户体验。

    14 引用 • 69 回帖 • 176 关注
  • Sandbox

    如果帖子标签含有 Sandbox ,则该帖子会被视为“测试帖”,主要用于测试社区功能,排查 bug 等,该标签下内容不定期进行清理。

    425 引用 • 1250 回帖 • 598 关注
  • Eclipse

    Eclipse 是一个开放源代码的、基于 Java 的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。

    76 引用 • 258 回帖 • 631 关注
  • Windows

    Microsoft Windows 是美国微软公司研发的一套操作系统,它问世于 1985 年,起初仅仅是 Microsoft-DOS 模拟环境,后续的系统版本由于微软不断的更新升级,不但易用,也慢慢的成为家家户户人们最喜爱的操作系统。

    226 引用 • 476 回帖
  • 酷鸟浏览器

    安全 · 稳定 · 快速
    为跨境从业人员提供专业的跨境浏览器

    3 引用 • 59 回帖 • 45 关注
  • 自由行
    2 关注
  • 脑图

    脑图又叫思维导图,是表达发散性思维的有效图形思维工具 ,它简单却又很有效,是一种实用性的思维工具。

    31 引用 • 96 回帖
  • OnlyOffice
    4 引用 • 23 关注
  • 程序员

    程序员是从事程序开发、程序维护的专业人员。

    586 引用 • 3538 回帖
  • OneNote
    1 引用 • 3 回帖
  • C++

    C++ 是在 C 语言的基础上开发的一种通用编程语言,应用广泛。C++ 支持多种编程范式,面向对象编程、泛型编程和过程化编程。

    107 引用 • 153 回帖
  • GitHub

    GitHub 于 2008 年上线,目前,除了 Git 代码仓库托管及基本的 Web 管理界面以外,还提供了订阅、讨论组、文本渲染、在线文件编辑器、协作图谱(报表)、代码片段分享(Gist)等功能。正因为这些功能所提供的便利,又经过长期的积累,GitHub 的用户活跃度很高,在开源世界里享有深远的声望,并形成了社交化编程文化(Social Coding)。

    210 引用 • 2040 回帖