7

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

jschmier
  • 15,458
  • 6
  • 54
  • 72
AD.
  • 389
  • 1
  • 5
  • 20
  • I think there are two separate questions here. You should address them separately. – Joel Feb 23 '10 at 12:22
  • 2
    please add more detail, for example why exactly do you want to disable stack trace ? what do you exactly mean by "disable stacktrace" (as it's just the chain of exceptions) – Valentin Rocher Feb 23 '10 at 12:24
  • 2
    I think that you are giving your users poor service here. An SDK not giving helpful exceptions? – Thorbjørn Ravn Andersen Feb 23 '10 at 13:10
  • "My requirement is that anyone using my Runtime jars should not be able to debug the code that is written" - this is a horrible requirement, and a horrible approach to try to meet this "requirement". – Nate Feb 23 '10 at 14:27
  • @user279436: is this for mobile application development? Anyway... You are mistaken if you think that because you have a public API you cannot use Proguard. You can use Proguard to obfuscate all the parts of your SDK that are not publicly accessible. This is a very convenient and very powerful feature of Proguard. – SyntaxT3rr0r Feb 23 '10 at 14:33
  • 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. – AD. Feb 23 '10 at 14:43
  • 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... – AD. Feb 23 '10 at 15:05

6 Answers6

12

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.

Anand Varkey Philips
  • 1,811
  • 26
  • 41
jarnbjo
  • 33,923
  • 7
  • 70
  • 94
  • 2
    Replacing `fillInStackTrace` for all exceptions is liable to break things; e.g. Java security. – Stephen C Feb 23 '10 at 13:00
  • 1
    @Stephen: Do you care to explain why, or should it be obvious? – jarnbjo Feb 23 '10 at 13:33
  • IIRC, some security checks involve examining the callstack to see if the caller is "privileged" code. IIRC this relies on fillInStackTrace. – Stephen C Feb 23 '10 at 14:07
  • 3
    also you want 'return this', not 'return null', otherwise you violate the javadoc of fillInStackTrace() – Matt McHenry Feb 24 '10 at 01:25
  • See com.sun.org.apache.xerces.internal.parsers.AbstractDOMParser.Abort –  Jul 12 '16 at 17:07
  • Yea sure. It works (i.e. removes the stacktrace) and it will be harmless for many (even most) exceptions. But doing it for all exceptions is risky. IMO. Unless you have researched the Java SE codebases and your dependencies for all cases of classes that introspect stacktraces. – Stephen C Sep 13 '22 at 12:32
  • @StephenC I am not sure why you pick up an almost 13 years old answer now, but for quite some time, you have had no guarantee anymore that exceptions are filled with stack traces. If an exception is recurringly thrown from the same location, the JVM will optimize away the stack trace generation for you anyway. I don't remember when this behaviour was introduced, but if you want to disable it and actually force a stack trace generation for all exceptions, you have to run the VM (at least the Oracle VM) with the `-XX:-OmitStackTraceInFastThrow` option to disable this optimization. – jarnbjo Sep 13 '22 at 20:58
  • @StephenC If you need the stack trace, e.g. for security reasons to verify from where the current code has been invoked, the method `Thread#getStackTrace()` was introduced in Java 5 and should be used to get the current stack trace instead of the old workaround, which required you to throw an exception to get the current stack trace. Java 5 was released in 2004. There is no reason to believe that there still is code in the JDK code base relying on unreliable stack traces from exceptions. – jarnbjo Sep 13 '22 at 21:03
7
  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.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • If I may share my experience: I once wrote a very good java solution for a simple but costly operation. My license with the customer was that they pay me monthly for as long as they are using the product. One day, they stopped paying. Through unofficial channels, I found out that they have analyzed my code and hired someone cheaper to capitalize on all the business logic I've learned (which you can see neatly in the code but took me ages to aggregate). I've since then developed my own native programming language and compiler, which are secret. Good luck analyzing that! – DraxDomax Jan 03 '20 at 15:56
  • The assumption is that "if your code is easy to read, it's therefore easy to program and, therefore was never worth anything". That's like the old joke: "500 bucks? It took you only 15 minutes to fix the leak!" - "but it took me 25 years to know how to find it!". – DraxDomax Jan 03 '20 at 16:02
  • 1
    Your mistake was that you tried to turn your application into an income stream. You should have just sold it to them for a once-off payment. If you wanted an income stream you should have made the application a service that runs on hardware that you control. I guess the second mistake was not suing their pants off. But here's the thing. The steps that the OP is proposing to do would not have stopped a determined reverse engineer anyway. – Stephen C Jan 04 '20 at 04:23
  • Out here? You are in the UK right? They have a sound legal system, right? If you have taken care in drawing up the contract / license agreement, reverse engineering should be a clear breach of contract. Find a law firm who will work for a contingency fee ... – Stephen C Jan 06 '20 at 13:11
  • I wanted to avoid explaining the story of my life :) I do live in the UK but I've also lived in several other countries, where the idea of IP is considered laughable. Even UK companies are (sometimes) strategically NOT relying on the concept of IP. I worked for a HUGE company where they intentionally did not file for patents. The technology in question is brilliant and yet simple to copy. A patent would imply revealing details about that technology to the public, who could be in the UK or NOT. Assuming "you could sue their pants off" isn't an airtight strategy. – DraxDomax Jan 06 '20 at 14:35
3

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

Thomas Pornin
  • 72,986
  • 14
  • 147
  • 189
  • 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. – AD. Feb 23 '10 at 12:59
  • 2
    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... – AD. Feb 23 '10 at 13:01
  • 1
    So why not distribute separate runtime and development jars, where the runtime jars are obfuscated? – Chinmay Kanchi Feb 23 '10 at 15:23
2

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

Joel
  • 29,538
  • 35
  • 110
  • 138
1

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);
1

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

Mikhail Kholodkov
  • 23,642
  • 17
  • 61
  • 78