Java 仅获取堆栈跟踪的前N行
我有一个工厂方法,它从ID调用返回一个对象 模拟代码:Java 仅获取堆栈跟踪的前N行,java,exception,stack-trace,Java,Exception,Stack Trace,我有一个工厂方法,它从ID调用返回一个对象 模拟代码: public static Object getById(String id) { Object o = CRUD.doRecovery(Class, id); if(o == null) { printLogMessage("recovery by ID returned Null: " + id); // would really like to show only a few lin
public static Object getById(String id) {
Object o = CRUD.doRecovery(Class, id);
if(o == null) {
printLogMessage("recovery by ID returned Null: " + id);
// would really like to show only a few lines of stack trace.
}
return o;
}
如何仅显示堆栈跟踪的前N行(因此我知道该方法的调用方),而不将整个堆栈跟踪转储到日志上或必须依赖外部libs?此方法显示堆栈跟踪的
I
行,跳过前两行
public static String traceCaller(Exception ex, int i) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
StringBuilder sb = new StringBuilder();
ex.printStackTrace(pw);
String ss = sw.toString();
String[] splitted = ss.split("\n");
sb.append("\n");
if(splitted.length > 2 + i) {
for(int x = 2; x < i+2; x++) {
sb.append(splitted[x].trim());
sb.append("\n");
}
return sb.toString();
}
return "Trace too Short.";
}
publicstaticstringtracecaller(异常exinti){
StringWriter sw=新的StringWriter();
PrintWriter pw=新的PrintWriter(sw);
StringBuilder sb=新的StringBuilder();
例如printStackTrace(pw);
字符串ss=sw.toString();
String[]splitted=ss.split(“\n”);
某人附加(“\n”);
如果(拆分长度>2+i){
对于(int x=2;x
前两行是异常名称和调用traceCaller()
的方法。如果要显示这些线,请调整它
感谢转到@()了解StringWriter PrintWriter的想法如果您只想截断堆栈跟踪,您可以将整个堆栈跟踪打印到StringWriter,然后删除不需要的内容:
public static void main(String[] args) throws ParseException {
try {
throw new Exception("Argh!");
} catch (Exception e) {
System.err.println(shortenedStackTrace(e, 1));
}
}
public static String shortenedStackTrace(Exception e, int maxLines) {
StringWriter writer = new StringWriter();
e.printStackTrace(new PrintWriter(writer));
String[] lines = writer.toString().split("\n");
StringBuilder sb = new StringBuilder();
for (int i = 0; i < Math.min(lines.length, maxLines); i++) {
sb.append(lines[i]).append("\n");
}
return sb.toString();
}
您可以使用
ex.getStackTrace()
获取堆栈元素,StackTraceeElement
包含一行完整的堆栈,然后根据需要打印
StackTraceElement[] elements = ex.getStackTrace();
print(elements[0]);
根据你的要求,我假设你没有例外。在这种情况下,您可以从以下位置获取当前堆栈跟踪:
StackTraceElement[] elements = Thread.currentThread().getStackTrace()
这将告诉您几乎所有您需要知道的关于代码中您来自何处的信息。番石榴可能会有所帮助。例如,我们只希望看到前十行:
log.error("Error:", Joiner.on("\n").join(Iterables.limit(asList(ex.getStackTrace()), 10)));
对于e.printStackTrace()的缩写版本: 异常e=。。。 System.out.println(例如toString()); StackTraceElement[]元素=e.getStackTrace();
对于(int i=0;i示例)显示第五行第一行:
final int nbLinesToShow=5;
试一试{
/*你的代码在这里*/
}捕获(最终NullPointerException e){
//捕捉错误
最终StackTraceElement[]元素=e.getStackTrace();
System.err.println(
“====================================================\n”+“[ERROR]lorem ipsum”);
对于(int i=0;i
感谢@BrianAgnew()提供StringWriter
PrintWriter
idea.IMO您应该将此评论作为答案的一部分。对于问题中要求的非异常用例,最全面的答案。只需输出“元素”的前两个元素数组的格式对您来说很方便。警告一句,Stacktraces的计算成本非常高。您将看到性能在4个数量级上恶化。不要将此用于高性能函数!进行分析,然后将此想法放入容器中,并传递一些标识符作为参数。然后每个调用方都必须使用som这是一种通过契约进行方法调用的自我识别论证。虽然不方便,但速度要快得多。性能不是问题,因为我们处理的是逻辑异常,例如,当应用程序的某个部分引用了不存在的实体id时。然后,我们可以确定违规者。我认为让调用方识别自己是一种挑战一个附加的耦合层,我更愿意以性能为代价。但是mikea的答案非常优雅,我正在绿化它。最内部的方法调用在索引0处,main在索引长度-1处。请参阅一个复制堆栈跟踪的示例(如果您碰巧有完整的异常对象)。请不要使用堆栈跟踪来了解方法的调用方。这非常昂贵(比较它也有一些分析数据)。而是使用第二个参数,并根据合同要求调用方使用一些有意义的自识别ID。“不必依赖外部libs”应该是Joiner.on(“\n”)。join(Iterables.limit(Arrays.asList(例如getStackTrace()),10))
在提出的问题中不会引发异常;因此这不是给定问题的答案。
log.error("Error:", Joiner.on("\n").join(Iterables.limit(asList(ex.getStackTrace()), 10)));
Exception e = ...
System.out.println(e.toString());
StackTraceElement[] elements = e.getStackTrace();
for(int i = 0; i<elements.length && i < STACK_TRACE_LIMIT; i++) {
System.out.println("\tat "+elements[i]);
}