如何在 Java 程序中禁用堆栈跟踪生成?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2317983/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 20:35:31  来源:igfitidea点击:

How to disable stack trace generation in a java program?

javadebuggingstack-trace

提问by AD.

I want to disable the stack trace getting generated when an exception is thrown. I have used,

我想禁用引发异常时生成的堆栈跟踪。我用过了,

Runtime.getRuntime().traceInstructions(false);
Runtime.getRuntime().traceMethodCalls(false);

but still i could see the trace getting generated. How can you do that? Also i need to detect whether some one is debugging my class.

但我仍然可以看到生成的痕迹。你怎么能这样做?我还需要检测是否有人在调试我的课程。

I want to disable all exception traces. I cannot use obfuscation since my product is an SDK which will be used in development. I am offering a Runtime also which is used when people want to deploy their applications built using my SDK. My requirement is that anyone using my Runtime jars should not be able to debug the code that is written...or atleast i will make it tough to debug by avoiding the stack trace generation from my runtime jars.

我想禁用所有异常跟踪。我不能使用混淆,因为我的产品是一个将用于开发的 SDK。我还提供了一个运行时,当人们想要部署使用我的 SDK 构建的应用程序时,会使用它。我的要求是任何使用我的运行时 jar 的人都不能调试编写的代码……或者至少我会通过避免从我的运行时 jar 中生成堆栈跟踪来使调试变得困难。

One way that i have found is that all the exceptions that are originating from my runtime jars, i would just catch them and set an empty StackTraceElement array on the exception object and re-throw it...

我发现的一种方法是,所有源自我的运行时 jar 的异常,我只会捕获它们并在异常对象上设置一个空的 StackTraceElement 数组并重新抛出它......

Why such requirement? Suppose you a develop an application using my SDK.(SDK jars cannot bundled with your application..i have restricted it and thats final :) !!) Now to run your application on your client's machine you(or client) needs to install the Runtime on client's machine and run your application. Now what if your client starts developing his own applications using my Runtime jars!! Thats a threat to my business....Thats why the horrible requirement.

为什么有这样的要求?假设您使用我的 SDK 开发一个应用程序。(SDK jar 不能与您的应用程序捆绑在一起。我已经对其进行了限制,这就是最终结果:) !!)现在要在您的客户端机器上运行您的应用程序,您(或客户端)需要安装在客户端机器上运行并运行您的应用程序。现在,如果您的客户开始使用我的运行时 jar 开发他自己的应用程序怎么办!!那是对我的生意的威胁....这就是可怕的要求的原因。

Why disable stack trace?
By disabling the stack trace generation or method call trace generation i wanted to make developing code with my Runtime jars difficult and thats why i started my question in that way...do suggest some other solution to achieve such a requirement...

为什么要禁用堆栈跟踪?
通过禁用堆栈跟踪生成或方法调用跟踪生成,我想让我的运行时 jar 开发代码变得困难,这就是为什么我以这种方式开始我的问题......建议一些其他解决方案来实现这样的要求......

采纳答案by Thomas Pornin

There are a few intricate parts of the JVM (at least, Sun's implementation of the JVM) which do not work if stack trace generation is disabled (I saw this in the implementation of some support methods for reflection). So I do not think that stack trace generation can be disabled at all. The Runtime.trace*()methods are about something else (a debugging tool much more thorough than stack traces).

如果禁用堆栈跟踪生成,JVM 有一些复杂的部分(至少,Sun 的 JVM 实现)将无法工作(我在一些反射支持方法的实现中看到了这一点)。所以我认为根本无法禁用堆栈跟踪生成。这些Runtime.trace*()方法是关于别的东西(一个比堆栈跟踪更彻底的调试工具)。

In all generality, any Java code can be transparently analyzed, if only through bytecode instrumentation (bytecode modified with extra instructions when it is loaded). The only known defense against such analysis (I am assuming that you are trying to keep your code internals confidential) is obfuscation. See for instance ProGuard. Obfuscation will make stack traces useless to any over-inquisitive user (and, sadly, it also makes debugging very difficult, for the same reasons).

总的来说,任何 Java 代码都可以被透明地分析,只要通过字节码检测(加载时用额外指令修改字节码)。唯一已知的针对此类分析的防御措施(我假设您正在尝试对代码内部保密)是混淆。参见例如ProGuard。混淆将使任何过度好奇的用户都无法使用堆栈跟踪(而且,遗憾的是,出于同样的原因,它也使调试变得非常困难)。

回答by jarnbjo

I'm also curious on why you want to do this, but if you really have your reasons, you have at least two options:

我也很好奇你为什么要这样做,但如果你真的有你的理由,你至少有两个选择:

If you want to disable stack trace generation for your own Exception implementations, you can simply override the fillInStackTrace method:

如果你想为你自己的异常实现禁用堆栈跟踪生成,你可以简单地覆盖 fillInStackTrace 方法:

public static class MyException extends Exception {
    @Override
    public Throwable fillInStackTrace() {
        return this;
    }       
}

If you want to disable it for allexceptions, you can use a byte code instrumentation agent to replace the fillInStackTrace method in the Throwable class. That will however only work for Java 6, since you in Java 5 are not allowed to replace a native method (fillInStackTrace) with a Java method using instrumentation.

如果要针对所有异常禁用它,可以使用字节码检测代理替换 Throwable 类中的 fillInStackTrace 方法。然而,这仅适用于 Java 6,因为在 Java 5 中不允许使用检测的 Java 方法替换本机方法 (fillInStackTrace)。

回答by Stephen C

  1. I don't think it is possible for code to know that it is being debugged, except by indirect (and unreliable) means like measuring how long it takes to execute code sequences.

  2. It is not possible to disable all stacktraces. You candisable stracktraces for exception classes that you define yourself, by overriding Throwable.fillInStackTrace()to do nothing. But that won't work for classes that you cannot change.

  1. 我认为代码不可能知道它正在被调试,除非通过间接(并且不可靠)的方式,比如测量执行代码序列需要多长时间。

  2. 不可能禁用所有堆栈跟踪。您可以通过覆盖Throwable.fillInStackTrace()不执行任何操作禁用您自己定义的异常类的 stracktraces 。但这不适用于您无法更改的课程。

But if you are thinking of doing these things to prevent reverse engineering, you would be wasting your time even if you could do it. It would be simple for a hacker to identify your application's anti-reverse-engineering code and edit the relevant bytecode files to disable it.

但是,如果您正在考虑做这些事情来防止逆向工程,即使您能做到,您也是在浪费时间。黑客很容易识别您的应用程序的反逆向工程代码并编辑相关的字节码文件以禁用它。

EDIT- I've revised my opinion on what you are trying to do. Given that what you are doing is distributing an SDK which you are expecting your customers to embed in their own applications, disabling stacktraces for the entire Java application counts as customer hostile behaviour, IMO. As a side-effect of protecting your "precious" IP, you are making it hard for the customer/developer to debug her own code. Even code that doesn't have your precious methods on the call stack!

编辑- 我已经修改了我对你正在尝试做的事情的看法。鉴于您正在做的是分发一个 SDK,您希望您的客户将其嵌入到他们自己的应用程序中,禁用整个 Java 应用程序的堆栈跟踪被视为 客户敌对行为,IMO。作为保护“宝贵”IP 的副作用,您使客户/开发人员难以调试自己的代码。即使是调用堆栈上没有您宝贵方法的代码!

If I was a customer, I'd probably prefer that you shipped obfuscated code than do this. But most likely, I'd try VERY HARD to find an alternative software supplier that didn't treat its paying customers as thieves.

如果我是客户,我可能更喜欢你发布混淆代码而不是这样做。但最有可能的是,我会非常努力地寻找替代软件供应商,该供应商不会将其付费客户视为小偷

回答by Joel

Do you want to disable it for all exceptions?

你想为所有例外禁用它吗?

Without knowing what you are trying to achieve, I would say this is the wrong path to go down. If you expect an exception to be thrown that you are happy to ignore you should explicitly catch it and handle it (where handling it can simply mean ignoring it, or logging a short message without the full stack trace).

在不知道您想要实现什么的情况下,我会说这是错误的道路。如果您希望抛出一个您乐于忽略的异常,您应该明确捕获它并处理它(处理它可以简单地意味着忽略它,或者记录一条没有完整堆栈跟踪的短消息)。

回答by Mikhail Kholodkov

You can redirect all exceptions to a different location, for example:

您可以将所有异常重定向到不同的位置,例如:

Thread.setDefaultUncaughtExceptionHandler(
                (t, e) -> System.err.println("There's nothing to see here"));

Or simply:

或者干脆:

Thread.setDefaultUncaughtExceptionHandler(null);

NOTE: Never ever use the code above in Production, unless you'd like to give your colleagues a hard time

注意:永远不要在生产中使用上面的代码,除非你想让你的同事很难过

回答by Tomislav Pokrajcic

Throwable.setStackTrace(StackTraceElement[] stackTrace) will block any additions to stackTrace after its call:

Throwable.setStackTrace(StackTraceElement[] stackTrace) 将在调用后阻止对 stackTrace 的任何添加:

Throwable t = new Throwable();
StackTraceElement[] myStackTrace = new StackTraceElement[] {
 new StackTraceElement("MySDKClass","MySDKMethod","MySDKFile",0)
};
t.setStackTrace(trace);