Stacktraces告诉了事实。 但事实并非如此。

我们公司致力于使软件错误的原因对开发人员和运营透明。 与替代解决方案相反, 我们将问题的位置浮出水面,使您指向源代码中的恶意行。 即使我们目前以检测内存泄漏的能力而闻名,但我们也正在扩展到其他领域。 为了给您一些有关我们研究方向的提示,我们决定通过三个示例进行分享。

这些示例归结为JVM功能,以提供有意义的堆栈跟踪。 在许多情况下,stacktrace确实包含解决问题所需的所有信息。 在其他情况下,它只是浮​​出水面,不知道可能是什么引起了潜在的问题。 让我用触发以下臭名昭著的错误消息的三个示例进行说明:

  • java.lang.OutOfMemoryError:无法创建新的本机线程
  • java.io.IOException:系统中打开的文件过多
  • java.lang.OutOfMemoryError:Java堆空间

所有示例都使用简单的代码片段进行了说明,从而使潜在问题更易于理解。

线程太多

static void createTooManyThreads() {
	try {
		for (int i = 0; i < TOO_MANY; i++) {
			Thread t = new Thread(new Runnable() {

				public void run() {
					try {
						Thread.sleep(3000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			});
			t.start();
		}
	} catch (OutOfMemoryError e) {
		e.printStackTrace();
	}
}

在上面的代码中,我们一直在启动线程,直到达到系统限制并遇到“ java.lang.OutOfMemoryError:无法创建新的本机线程”消息。 理解问题与线程限制耗尽有关,这有什么问题? 让我们仔细看看stacktrace:

java.lang.OutOfMemoryError: unable to create new native thread
	at java.lang.Thread.start0(Native Method)
	at java.lang.Thread.start(Thread.java:693)
	at eu.plumbr.demo.MisleadingStacktrace.createTooManyThreads(MisleadingStacktrace.java:34)
	at eu.plumbr.demo.MisleadingStacktrace.main(MisleadingStacktrace.java:16)

问题就一直盯着我们的脸-有人告诉我们添加最后一根稻草将驼背弄断了。 同时,我们没有一个线索是,骆驼已经被完全装载了。 如果错误消息还包含一种方法,以查看在我们最后一次尝试启动最后一个调用导致上述堆栈跟踪之前,哪个调用堆栈正在消耗线程的不同跟踪,那么它将使开发人员的工作变得更加轻松。

但是让我们看一下相同的问题–从另一个角度来看资源消耗:

打开的文件太多

再次,让我们从示例代码开始:

static void createTooManyFiles() {
	try {
		for (int i = 0; i < TOO_MANY; i++) {
			File f = new File(PATH_TO_FILE + i + ".txt");
			f.createNewFile();
			OutputStream s = new FileOutputStream(f);
			s.write(1);
		}
	} catch (IOException e) {
		e.printStackTrace();
	}
}

该示例尝试创建许多文件,并且仅在每个文件中写入一个整数而不关闭先前的文件。 再一次,运行上面的代码会导致堆栈跟踪不太有用:

java.io.IOException: Too many open files in system
	at java.io.UnixFileSystem.createFileExclusively(Native Method)
	at java.io.File.createNewFile(File.java:947)
	at eu.plumbr.demo.MisleadingStacktrace.createTooManyFiles(MisleadingStacktrace.java:45)
	at eu.plumbr.demo.MisleadingStacktrace.main(MisleadingStacktrace.java:17)

现在,以不同的方式掩盖了相同的问题-我们确实得到了这样的消息:我现在尝试过多地打开一个文件,但是-谁打开了另一个文件来向JVM施加压力,使其无法完成运行?

如果您仍然不确定,请看第三个示例,即我们目前的面包和黄油:

消耗太多内存

代码示例再次很简单–我们采用数据结构并不断增加结构,直到可用堆耗尽为止:

static void createTooLargeDataStructure() {
	try {
		List l = new ArrayList();
		for (int i = 0; i < TOO_MANY; i++) {
			l.add(i);
		}
	} catch (OutOfMemoryError e) {
		e.printStackTrace();
	}
}

运行代码会给您带来臭名昭著的java.lang.OutOfMemoryError:Java堆空间消息。 如果所讨论的数据结构是通过源代码中的不同可能位置来填充的,那么这又很难解释。

我知道所有C语言开发人员现在都无奈地耸了耸肩,因为在他们的世界中,以上所有内容都只是采取段错误的形式,但是–如果我们走得那么远,为什么我们不能做得更好? 我相信我们可以做到,那就是我们将要做的–为您找到性能瓶颈

如果您对完整的代码示例感兴趣,可以在此处下载。 该代码在JDK 7u25上的OS X 10.9的Macbook Pro上运行。 之后,请确保您不会错过未来有趣内容的更新,并订阅我们的Twitter feed


翻译自: https://www.javacodegeeks.com/2013/11/stacktraces-are-telling-the-truth-but-not-the-whole-truth.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值