关于编写Java程序让Jvm崩溃

今天在书上看到一个作者提出一个问题“怎样通过编写Java代码让Jvm崩溃”,我看了之后也不懂。带着问题查了一下,百度知道里面有这样一个答案:


1 package jvm;

2

3 public class Crash {

4     public static void main(String[] args) {

5

6         //Object[] o = {“abc”};初始值赋值,不会有影响。

7         Object[] o = null;

8

9         while (true) {

10             o = new Object[] { o };

11             //输出的话,jvm就不会崩溃。

12             //System.out.println(o);

13         }

14     }

15 }

  程序运行十几秒之后,控制台会出现这样的错误:

  Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

  at jvm.Crash.main(Crash.java:10)

  很明显,超出内存空间错误。

  我将原程序随意改了一下,如赋初始值等,对程序无影响。

  可是我将死循环中的o输出在控制台的时候,jvm居然一直都不崩,为什么输出的话,就不会超出内存空间呢?

  我看来,原程序能够使Jvm崩溃,是因为死循环中,通过旧对象,不断创建出新的对象,即创造的对象是互相引用的,所以GC是不会回收它们的,造成堆栈溢出。

  仿照这个例子,我写了一个简单的类,模仿例子程序中的数组,如下:


1 package jvm;

2

3 public class JvmBean {

4

5     JvmBean bean = new JvmBean(this);

6

7     public JvmBean(JvmBean bean){

8         this.bean = bean;

9     }

10 }

  然后简单测试,如下:


1 package jvm;

2

3 public class MyCrash {

4

5     public static void main(String[] args) {

6         JvmBean j = null;

7         while(true){

8             j = new JvmBean(j);

9             //无论输出不输出,jvm都会崩溃

10             //System.out.println(j);

11         }

12     }

13 }

 结果便是控制台输出如下的错误:


Exception in thread "main" java.lang.StackOverflowError

at jvm.JvmBean.<init>(JvmBean.java:5)

at jvm.JvmBean.<init>(JvmBean.java:5)

at jvm.JvmBean.<init>(JvmBean.java:5)

at jvm.JvmBean.<init>(JvmBean.java:5)

at jvm.JvmBean.<init>(JvmBean.java:5)

  一长串的"at jvm.JvmBean.<init>(JvmBean.java:5)",后面的被我省略了。

  结果看来,同样也造成了jvm崩溃,可是错误类型跟例子程序的不同,说堆栈溢出错误,并且无论是否输出,错误都一样发生,为什么呢?

  由于评论的两位老兄的热心指点,两个问题都水落石出了!

  这里过一下整个流程。

  第一个异常 结合天添老兄说的,Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at jvm.Crash.main(Crash.java:10)是因为程序无法申请到足够的内存的时候抛出的异常,Object数组o不断指向新的Object数组,数组元素是原来的Object数组,这使得Object维数越来越高。不断申请内存空间,最终导致超出jvm中堆的最大值。堆内存溢出。为什么输出打印,时间会延长呢?yahokuma老兄一言惊醒梦中人!输出打印的话,虚拟机并不是不会崩溃,而是崩溃的时间大大延长了。而崩溃时间延长其实是假象,是因为输出属于IO事件,每次输出CPU都被中断,IO很耗时,所以,感觉上才会时间延长。

  第二个异常,yahokuma 老兄在下面评论中已经说的很清楚了,我这里搬过来——“类内部的静态属性 > 静态块 > 对象属性 > 构造方法。注意这一点,那就是说 bean属性会先于JvmBean的构造函数被初始化。在你main函数中,new一个 JvmBean的构造函数之前,类内部的JvmBean对象要优先被初始化,这个类内部的属性bean的内部同样也包含了一个JvmBean对象需要被初始化,成循环调用,造 成了栈溢出。”所以异常才会是这个——Exception in thread "main" java.lang.StackOverflowError

  我把原JvmBean改一下


1 package jvm;

2

3 public class JvmBean {

4

5     JvmBean bean = null;

6

7     public JvmBean(JvmBean bean){

8         this.bean = bean;

9     }

10 }

  这样最终得到的结果跟第一个例子一样了。

  如何使Jvm崩溃呢?如果想使它堆内存空间不足,造成典型的内存泄漏,可以创建对象,使它们不断向深层次引用。产生Exception in thread "main" java.lang.OutOfMemoryError: Java heap space 这样的错误。如果想使他们栈空间不足,最简单的,就是在方法里,如构造方法里不断申请新的内存空间就够了,如我第二个错误例子的示范。

最新内容请见作者的GitHub页:http://qaseven.github.io/

时间: 2024-08-17 15:32:25

关于编写Java程序让Jvm崩溃的相关文章

编程-Eclipse环境下编写Java程序,使用float类型的数据为什么无法进行算数运算?

问题描述 Eclipse环境下编写Java程序,使用float类型的数据为什么无法进行算数运算? float f=5+5.5; 或者 float f ; f= 1*5.5; 这两个均会报错,我就纳闷了.为什么这样不行?后来我又试了: int a= 5; float f ; f= a*5.5; 还是不行,报错的语句就是给f赋值的语句. 请问为什么?C++下亲测这三者均可运行,难道这是Java的特性吗?不可能啊,如果这种操作都会编译报错,那这float基本上就没用处了,这太不科学了. 为了避免一些网

Eclipse下编写java程序突然不会自动生成R.java文件和包的解决办法_java

下面给大家介绍几种比较常见的解决办法,具体内容如下: 1.有时候eclipse不自动编译,把project clean一下,让R.java重新生成 2.选择菜单 Project >> Clean ,前提是勾选上 Bulid Automatically(自动构建部署) , 点Clean后会重新构建项目,因为一般情况下,R.java文件在这个时候会重新更新生成一边,如果工程有错,就不会自动生成. 3.选择工程,右键 Android Tools >> Fix Project Proper

vs2013编写java程序出错

问题描述 vs2013编写java程序出错 下载插件之后,建立项目,无法编译 解决方案 估计是编译就没通过,没有产生jar目标文件,检查你的代码.写java还是用eclipse吧.

如何使用记事本编写java程序

  新建java第一种方法 1首先右击鼠标,新建一个文本文档. 2更改文本文档的后缀名为 .java .注意文件名必须和类名相同. 如果你的电脑没有显示后缀名的话需要对电脑进行一定的设置. 3打开计算机--组织--文件夹选项--查看--将隐藏文件夹选项取消勾选即可. 建议将这个选项取消勾选,有很多的恶意程序会侵入我们的电脑,取消勾选可以很好的查看病毒等文件的类型. 4右击建好的文档,选择编辑即可进行java的编写. 在编写的时候我们有一定的格式,java语言的格式是为了我们日后更改程序方便而规定

使用记事本编写java程序全过程图解_java

Java是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由Sun Microsystems公司于1995年5月推出的Java程序设计语言和Java平台(即JavaSE, JavaEE, JavaME)的总称.Java 技术具有卓越的通用性.高效性.平台移植性和安全性,广泛应用于个人PC.数据中心.游戏控制台.科学超级计算机.移动电话和互联网,同时拥有全球最大的开发者专业社群. 新建java第一种方法 1首先右击鼠标,新建一个文本文档. 2更改文本文档的后缀名为 .java .注意文件名必

《Java 开发从入门到精通》—— 2.2 编写第一段Java程序

2.2 编写第一段Java程序    知识点讲解:光盘:视频PPT讲解(知识点)第2章编写第一段Java程序.mp4 当完成Java开发环境的安装工作后,接下来开始编写一段Java程序,并把这段Java程序进行编译运行,正式开始我们的编码之旅. 2.2.1 编写一段Java代码 打开记事本,在记事本里编写下面的代码. public class First{ /*这是一个 main 方法*/ public static void main(String [] args){ /* 输出此消息 */

Java 程序员最喜欢的 11 款免费 IDE 编辑器

Java开发人员需要花费大量的时间埋头于Java代码中,使用各种不同的IDE(Intergrated Development Environment)来开发Java代码,所以下面我将为大家介绍11个不同的IDE,这些IDE提供了多种功能,如:构建Java应用.TestNG.调试.代码检查.代码帮助.JUNIT测试.多元重构.可视化GUI构建器和代码编辑器.Java和Maven构建工具.ant.数据建模和构建查询,等等. 1.NetBeans NetBeans是一款用Java编写的开源IDE,是I

Java程序员也应该知道的系统知识系列之内存

作者:林昊 上篇说到了Java程序和CPU的关系,对于多数实现的较好的Java应用程序而言,基本上随着CPU的核数增加或能力提升,系统能够支撑的并发量就可以稳步上升,但对于内存而言,是否也是这样呢,这篇我们就来看看Java程序和内存的关系.   和CPU一样,我们首先要知道机器上的内存的硬件状况,在linux下,可以通过dmidecode | grep -A16 "Memory Device$"命令来查看机器插了多少根内存条,以及每根内存条的具体型号,内存条的具体型号对Java应用的运

《Java和Android开发学习指南(第2版)》—— 1.2 第一个Java程序

1.2 第一个Java程序 本小节将强调Java开发中的步骤,即编写程序,将其编译为字节码以及运行字节码. 1.2.1 编写Java程序 可以使用任何文本编辑器来编写Java程序.打开一个文本编辑器,并且输入代码清单1.1中的代码.或者,如果你已经下载了本书配套的程序示例,只要将它复制到你的文本编辑器中就可以了. 如果你还没有下载代码,现在就可以从异步社区的Web站点下载示例.在前言的最后部分中,给出了下载地址.代码清单1.1 一个简单的Java程序 class MyFirstProgram {