java9中有一个stack walking api,它只允许我们获取最后两个堆栈帧。但是我被Java8困住了。在Java8中,我们可以使用 Thread.currentThread().getStackTrace()
或者 new Throwable().getStackTrace()
但是这两种方法都很慢,因为它们构造了整个堆栈跟踪。有没有办法限制堆栈跟踪中的帧数(例如只构造最后3帧)?
更新:我测试了stephen的代码,效果非常好。它确实减少了执行时间,具体取决于选择的深度。我发现有趣的是,它并没有减少创建新异常的时间,即使堆栈跟踪是在异常创建期间构造的,并以内部格式存储。大部分时间都花在将这种内部格式转换为 StackTraceElement
什么时候 getStackTrace()
被称为。因此,如果堆栈轨迹较浅,则转换它所需的时间当然要短。但是为什么在创建异常时不花更少的时间来创建堆栈跟踪的内部表示呢( new Throwable()
)?
public static void main(String[] args) throws IOException {
f1();
}
private static void f1() {
f2();
}
private static void f2() {
f3();
}
private static void f3() {
f4();
}
private static void f4() {
f5();
}
private static void f5() {
int sum = 0;
long l = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
Throwable throwable = new Throwable();
//comment out to test the internal representation -> StackTraceElement conversion
//StackTraceElement[] trace = throwable.getStackTrace();
//sum += trace.length;
}
long l2 = System.currentTimeMillis();
System.out.println(l2-l);
System.out.println(sum);
}
更新2:为了消除板凳问题,我存储了所有 Throwable
数组中的示例,然后在执行结束时,我随机检索其中一个示例并打印堆栈跟踪。我认为这将阻止为消除 new Throwable()
电话。
int sizez = 2000000;
Throwable[] th = new Throwable[sizez];
for (int i = 0; i < sizez; i++) {
th[i] = new Throwable();
//StackTraceElement[] trace = throwable.getStackTrace();
//sum += trace.length;
}
long l2 = System.currentTimeMillis();
System.out.println(l2-l);
System.out.println(sum);
Random rand = new Random();
StackTraceElement[] trace = th[rand.nextInt(sizez)].getStackTrace();
System.out.println(trace[0]);
1条答案
按热度按时间gg0vcinb1#
您可以使用jvm选项
-XX:MaxJavaStackTraceDepth=depth
限制堆栈跟踪的大小。但是,这适用于所有stacktraces,听起来并不是您所需要的。我不认为有一种方法可以根据具体情况来限制规模。