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

发布于 2024-08-23 00:43:51 字数 765 浏览 3 评论 0原文

我想禁用抛出异常时生成的堆栈跟踪。 我已经使用过,

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

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

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

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

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

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

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.

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...

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.

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...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

羞稚 2024-08-30 00:43:51

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

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

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

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

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:

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

If you want to disable it for all exceptions, 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.

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

  2. 不可能禁用所有堆栈跟踪。您可以通过重写 Throwable.fillInStackTrace() 来禁用自己定义的异常类的跟踪跟踪而不执行任何操作。
    但这对于您无法更改的类不起作用。

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

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

如果我是客户,我可能更希望您提供混淆的代码,而不是这样做。但最有可能的是,我会非常努力地寻找一个不将付费客户视为小偷的替代软件供应商

  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 can disable 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.

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!

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.

尽揽少女心 2024-08-30 00:43:51

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

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

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).

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).

唱一曲作罢 2024-08-30 00:43:51

您想对所有异常禁用它吗?

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

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).

能否归途做我良人 2024-08-30 00:43:51

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

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

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

Throwable t = new Throwable();
StackTraceElement[] myStackTrace = new StackTraceElement[] {
 new StackTraceElement("MySDKClass","MySDKMethod","MySDKFile",0)
};
t.setStackTrace(trace);
白日梦 2024-08-30 00:43:51

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

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

或者简单地:

Thread.setDefaultUncaughtExceptionHandler(null);

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

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文