百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

java堆栈信息不见了(java中堆栈分别存放什么数据)

toyiye 2024-07-04 09:11 10 浏览 0 评论


1. 问题描述

最近同事通过ELK查找异常日志发现,exception的栈不见了,如下所示:
异常信息:java.lang.NullPointerException
异常信息:java.lang.NullPointerException
异常信息:java.lang.NullPointerException

本地试了很多次一直都能打印出异常信息,那么前面那段只有简单的java.lang.NullPointerException,没有详细异常栈信息的原因是什么呢?于是他问怎么出现这个现象的,我跟他说这种情况是 JVM对一些特定的异常类型做了Fast Throw优化导致的

java.lang.NullPointerException
 ...
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

2. 什么是Fast Throw

JVM中有个参数:OmitStackTraceInFastThrow,就是省略异常栈信息将异常快速抛出。

2.1 JVM是如何做到快速抛出的呢?

JVM对一些特定的异常类型做了Fast Throw优化,如果检测到在代码里某个位置连续多次抛出同一类型异常的话,C2会决定用Fast Throw方式来抛出异常,而异常Trace即详细的异常栈信息会被清空。这种异常抛出速度非常快,因为不需要在堆里分配内存,也不需要构造完整的异常栈信息。相关的源码的JVM源码的graphKit.cpp文件中

源码地址

http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/file/tip/src/share/vm/opto/graphKit.cpp(从514行开始)

2.2 Fast Throw源码解析

//------------------------------builtin_throw----------------------------------
void GraphKit::builtin_throw(Deoptimization::DeoptReason reason, Node* arg) {
 bool must_throw = true;
 ... ...
 // If this particular condition has not yet happened at this
 // bytecode, then use the uncommon trap mechanism, and allow for
 // a future recompilation if several traps occur here.
 // If the throw is hot, try to use a more complicated inline mechanism
 // which keeps execution inside the compiled code.
 bool treat_throw_as_hot = false;
 if (ProfileTraps) {
 if (too_many_traps(reason)) {
 treat_throw_as_hot = true;
 }
 // (If there is no MDO at all, assume it is early in
 // execution, and that any deopts are part of the
 // startup transient, and don't need to be remembered.)
 // Also, if there is a local exception handler, treat all throws
 // as hot if there has been at least one in this method.
 if (C->trap_count(reason) != 0
 && method()->method_data()->trap_count(reason) != 0
 && has_ex_handler()) {
 treat_throw_as_hot = true;
 }
 }
 // If this throw happens frequently, an uncommon trap might cause
 // a performance pothole. If there is a local exception handler,
 // and if this particular bytecode appears to be deoptimizing often,
 // let us handle the throw inline, with a preconstructed instance.
 // Note: If the deopt count has blown up, the uncommon trap
 // runtime is going to flush this nmethod, not matter what.
 // 满足两个条件:1.检测到频繁抛出异常,2. OmitStackTraceInFastThrow为true,或StackTraceInThrowable为false
 if (treat_throw_as_hot
 && (!StackTraceInThrowable || OmitStackTraceInFastThrow)) {
 // If the throw is local, we use a pre-existing instance and
 // punt on the backtrace. This would lead to a missing backtrace
 // (a repeat of 4292742) if the backtrace object is ever asked
 // for its backtrace.
 // Fixing this remaining case of 4292742 requires some flavor of
 // escape analysis. Leave that for the future.
 ciInstance* ex_obj = NULL;
 switch (reason) {
 case Deoptimization::Reason_null_check:
 ex_obj = env()->NullPointerException_instance();
 break;
 case Deoptimization::Reason_div0_check:
 ex_obj = env()->ArithmeticException_instance();
 break;
 case Deoptimization::Reason_range_check:
 ex_obj = env()->ArrayIndexOutOfBoundsException_instance();
 break;
 case Deoptimization::Reason_class_check:
 if (java_bc() == Bytecodes::_aastore) {
 ex_obj = env()->ArrayStoreException_instance();
 } else {
 ex_obj = env()->ClassCastException_instance();
 }
 break;
 }
 ... ...
}

从源码可以看到默认对下面的Exception都做了Fast Throw。

  • NullPointerException
  • ArithmeticException
  • ArrayIndexOutOfBoundsException
  • ArrayStoreException
  • ClassCastException

OmitStackTraceInFastThrow和StackTraceInThrowable都默认为true,所以条件(!StackTraceInThrowable || OmitStackTraceInFastThrow)为true,即JVM默认开启了Fast Throw优化。

如果想关闭Fast Throw的优化,在启动参数加上配置

-XX:-OmitStackTraceInFastThrow,

StackTraceInThrowable保持默认配置即可。

3.验证结果

写一个简单的代码验证

public class JavaNPE extends Thread {
 private static int count = 0;
 @Override
 public void run() {
 try {
 System.out.println("getSimpleName is:"+this.getClass().getSimpleName() + " execute count:" + (++count));
 String str = null;
 System.out.println(str.length());
 } catch (Throwable e) {
 e.printStackTrace();
 }
 }
}
public class TestFastThrow {
 public static void main(String[] args) throws InterruptedException {
 JavaNPE javaNPE = new JavaNPE();
 ExecutorService executorService = Executors.newFixedThreadPool(10);
 for (int i = 0; i < Integer.MAX_VALUE; i++) {
 executorService.execute(javaNPE);
 //防止打出的日志太快
 Thread.sleep(2);
 }
 }
}

在没有加入-XX:-OmitStackTraceInFastThrow测试结果(NPE连续抛出5000+次就会丢失异常栈):

getSimpleName is:JavaNPE execute count:6666
java.lang.NullPointerException
	at com.jason.demo.demo.JavaNPE.run(JavaNPE.java:18)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
getSimpleName is:JavaNPE execute count:6667
java.lang.NullPointerException
	at com.jason.demo.demo.JavaNPE.run(JavaNPE.java:18)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
java.lang.NullPointerExceptiongetSimpleName is:JavaNPE execute count:6668
	at com.jason.demo.demo.JavaNPE.run(JavaNPE.java:18)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
getSimpleName is:JavaNPE execute count:6669
java.lang.NullPointerException
getSimpleName is:JavaNPE execute count:6670
java.lang.NullPointerException
getSimpleName is:JavaNPE execute count:6671
java.lang.NullPointerException
getSimpleName is:JavaNPE execute count:6672
java.lang.NullPointerException

加入-XX:-OmitStackTraceInFastThrow测试结果:

getSimpleName is:JavaNPE execute count:11325
java.lang.NullPointerException
	at com.jason.demo.demo.JavaNPE.run(JavaNPE.java:18)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
getSimpleName is:JavaNPE execute count:11326
java.lang.NullPointerException
	at com.jason.demo.demo.JavaNPE.run(JavaNPE.java:18)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
getSimpleName is:JavaNPE execute count:11327

参考:

https://www.oracle.com/technetwork/java/javase/relnotes-139183.html

https://stackoverflow.com/questions/2411487/nullpointerexception-in-java-with-no-stacktrace

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码