Is it possible for the compiler to remove statements used for debugging purposes (such as logging) from production code? The debug statements would need to be marked somehow, maybe using annotations.
It's easy to set a property (debug = true) and check it at each debug statement, but this can reduce performance. It would be nice if the compiler would simply make the debug statements vanish.
Two recommendations.
First:
for real logging, use a modern logging package like log4j or java's own built in logging. Don't worry about performance so much, the logging level check is on the order of nanoseconds. (it's an integer comparison).
And if you have more than a single log statement, guard the whole block:
(log4j, for example:)
if (logger.isDebugEnabled()) {
// perform expensive operations
// build string to log
logger.debug("....");
}
This gives you the added ability control logging at runtime. Having to restart and run a debug build can be very inconvenient.
Second:
You may find assertions are more what you need. An assertion is a statement which evaluates to a boolean result, with an optional message:
assert (sky.state != FALLING) : "The sky is falling!";
Whenever the assertion results in a false, the assertion fails and an AssertionError is thrown containing your message (this is an unchecked exception, intended to exit the application).
The neat thing is, these are treated special by the JVM and can toggled at runtime down to the class level, using a VM parameter (no recompile needed). If not enabled, there is zero overhead.
public abstract class Config
{
public static final boolean ENABLELOGGING = true;
}
import static Config.*;
public class MyClass
{
public myMethod()
{
System.out.println("Hello, non-logging world");
if (ENABLELOGGING)
{
log("Hello, logging world.");
}
}
}
The compiler will remove the code block with "Hello, logging world." in it if ENABLE_LOGGING is set to true because it's a static final value. If you use an obfuscator such as proguard, then the Config class will vanish too.
An obfuscator would also allow things like this instead:
public class MyClass
{
public myMethod()
{
System.out.println("Hello, non-logging world");
Log.log("Hello, logging world.");
}
}
import static Config.*;
public abstract class Log
{
public static void log(String s)
{
if (ENABLELOGGING)
{
log(s);
}
}
}
The method Log#log would reduce to nothing in the compiler, and be removed by the obfuscator, along with any calls to that method and eventually even the Log class would itself be removed.
Another possibility is to put the if statement within your logging function, you get less code this way, but at the expense of some extra function calls.
I'm also not a big fan of completely removing the debug code. Once you're in production, you'll probably need access to debug messages if something goes wrong. If you remove all of your code level debugging, than this isn't a possibility.
This "trick" seems to make your debug statements vanished
public static final boolean DEBUG = false;
if (DEBUG) { //disapeared on compilation }
The post said that javac is smart enough to check the static final boolean and exclude the debug statements. (I did not personally try it)
For logging, I personally donot like to see code like:
if (logger.isDebugEnabled()) {
logger.debug("....");
}
realImportantWork();
The logging things distracts me from the realImportantWork(). The right way for me is:
logger.debug("....");
realImportantWork()
plus the config which excludes all debug messages on Production.
I mean that the logger.isDebugEnabled() control should be the job of the logging framework, not my job. Most logging framework support concepts like "logger", "LogLevel".. which can do the trick.
Use Java Preprocessor? (google foo low but this is a link to the old Joel forums discussing it)
Java contains some sort of preprocessor of its own. It's called APT. It processes and generates code. At the moment I'm not sure how this should work (I haven't tried it). But it seems to be used for these kind of things.
I would also highly recommend using a logging framework.
The logger.IsDebugEnabled() is not mandatory, it is just that it can be faster to check whether the system is in the debug level before logging.
Using a logging framework means you can configure logging levels on the fly without restarting the application.
You could have logging like:
logger.error("Something bad happened")
logger.debug("Something bad happend with loads more detail")
To directly answer your question: I don't know.
But here is another solution to your problem:
In my mind, there are two statements that collide with each other here: "debug statements" and "production code".
What is the purpose of debug statements? Help to get rid of bugs while (unit) testing. If a piece of software is properly tested and works according to the requirements, debug statements are nothing else but OBSOLETE.
I strongly disagree with leaving any debug statements in production code. I bet nobody bothers testing side-effects of debug code in production code. The code probably does what it's supposed to do, but does it do more than that? Do all your #defines work correctly and really take ALL of the debug code out? Who analyzes 100000 lines of pre-processed code to see if all the debug stuff is gone?
Unless we have a different definition of production code, you should consider taking out the debug statements after the code is tested and be done with it.
Related
I have many lines i just use for debugging and helpers. Is there a way i can mark these so they do not compile when publishing a project but still can use when running/debugging my program within Eclipse? Even better would be to mark a certain field as debug only and discard everything that has to do with that field completely when publishing.
I understand this might get one in trouble when using fields like that and using that in critical parts of the code. But i often find myself initializing a lot of debug fields then comment them out which results in errors down the line if i do not comment those out as well.
So is there some way to handle this in a better and more efficient way?
Put your code inside an if statement that refers to a final static boolean constant in another class. An if statement like if (DEBUG) that effectively says if (false) (because DEBUG is false) is not compiled by the Java compiler.
public class Debug {
public final static boolean DEBUG = true; // or false
}
public class X {
public m() {
if (Debug.DEBUG) {
// Do some timing or displaying mouse positions, or whatever.
}
}
}
If you want to verify that this works, you can use the javap disassembler: the compiler won't generate code if your DEBUG constant is false, but if DEBUG is true it will.
For further reference, the Java Language Specification (linked) has a section on conditional compilation, "Example 13.4.9-2". This explains what I've described above.
Use the trace level of your favorite logger, e.g. log4j.
Yes. Use a logging framework.
A logging framework exists to allow developers to write out important events to either the standard command line, to a file, or anywhere else they desire. Java comes with a built-in (albeit primitive) logging framework: java.util.logging.
Here's a sample of it in action.
Logger logger = Logger.getLogger("foo-logger");
logger.log(Level.INFO, "This is a log statement at a rather standard logging level - use when you want to log information out.");
logger.log(Level.WARNING, "This is a log statement at a rather moderate logging level - use when things warrant looking into but aren't mission critical.");
logger.log(Level.SEVERE, "This is a log statement at a rather high logging level - use when an (often irrecoverable) error has occurred.");
If you use that, then you'll see something similiar to this in your terminal:
Aug 23, 2014 10:05:24 AM com.stackoverflow.sandbox.Formatting main
INFO: This is a log statement at a rather standard logging level - use when you want to log information out.
Aug 23, 2014 10:05:24 AM com.stackoverflow.sandbox.Formatting main
WARNING: This is a log statement at a rather moderate logging level - use when things warrant looking into but aren't mission critical.
Aug 23, 2014 10:05:24 AM com.stackoverflow.sandbox.Formatting main
SEVERE: This is a log statement at a rather high logging level - use when an (often irrecoverable) error has occurred.
Other frameworks such as Log4J2 are more intuitive as to what the levels mean, as well as offer simpler options to log out to wherever you desire.
i'm using System.out.println() (sout) for debugging and general state overview purposes while programming (which is especially helpful for network stuff). Since i want my code to be efficient at the end, is there a way to tell the java compiler to ignore souts?
I already tried some googling, but the solutions where very unsatisfying, like putting all souts inside an if with a global variable. (Tripling the lines and making code very unreadable if a lot of souts are needed)
Anyone know if such a compiler option exists (if not, why not?), or if there is some other more elegant solution then the one stated above. Thank you for your answers :)
Use logging. You can indicate a log level that normally won't be displayed, and with logging properties can be made to appear. This can be done controlled etc.
Logger.getLogger(getClass().getName()).log(Level.FINE, "...");
In fact there are many examples and aspects to logging. So if you want your code to be minimalistic but mature, use logging.
An alternative way would be to use unit tests, and to not output in the production code. This requires more strictness and allows to find regression errors.
And a third alternative would be to more liberally use (unchecked) exceptions, IllegalArgumentException, IllegalStateException. To have an informative fail-fast.
First I would like to say that the real answer to this question is to use a logging framework as others have shown.
But if you are committed to using System.out, you can still achieve the desired effect. In the below class, I change System.out (by using the System.setOut method) to another PrintStream that does not actually print anything.
import java.io.*;
class Sys
{
public static void main ( String [ ] args ){
System.setOut(new PrintStream(new OutputStream(){
#Override
public void write(int b){
}
}));
System.out.println("Hello World!");
}
}
My answer can be improved upon. For example, it will still convert objects to string for printing, but you can solve that by setting out to an overrided PrintStream class that does absolutely nothing.
But the more you improve upon it, the more you are just implementing a logging utility which someone else has already done. This is why I suggest logging is the real answer.
In teaching myself about Java errors and warnings, I have been exploring the documentation for java.util.logging.Logger. It seems as if everything within the Logger class is geared toward logging specific items--which makes sense from a practical persepctive.
However, I would like to be able to log everything that can be logged. It fits my learning style to look at everything that can be logged for a working program, then break things to see how the logfile changes. From there, it's easier for me to understand how to control what does and doesn't get logged.
I saw this post and this post with which I'm going to be starting, but I'm wondering if there are other resources that'd help me implement a "log everything" solution to increase my understanding of the class?
The logging classes will add messages to one or more appenders. You have to give it messages - it seems you're asking how you can log everything so I don't have to give a message to log. This isn't what loggers do. I think what you want is a debugger, and then step through your code.
Nothing logs on its own.
Given that you have two options:
Use a debugger instead. It matches more with your requirements. Step through the code and inspect variables on the fly. To use debugger, you can use any standard IDE like IntelliJ Idea or Eclipse.
Use AOP : Define an aspect which keeps logging all method parameters and return types. You could use Spring AOP for that
If you are a beginner, I would recommend option 1.
I am with the two other guys, but if you wanna see errors, you could use Exceptions with try-catch blocks like this:
try
{
//enter your code here
Test f = new Test();
}
catch(Exception e){
e.printStackTrace();
}
Is there a way to detect the end of the bootstrapping phase of the JVM?
edit::
so to provide a bit more context, what i am trying to do is to instrument the JDK. And this is a full blown instrumentation that records every LOAD, STORE, INVOKE byte code instruction. As the instructions are executed their data is sent to a static method, that is loaded from the xbootclasspath. This static method captures all this information and stores all of this as a trace for performing analysis at a later time.
Now, when i do this for the JDK, i do not want to disturb the way classes are loaded in the JVM, which might result in a program crash. I was guessing that the best way to go about it is to detect the point in time when the JVM is done bootstrapping, so that I can safely turn on my instrumentation thereafter. (I plan to not instrument any of the code, while the bootstrapping is taking place.) Is this even the right way to go about it?
In addition to my previous comment about looking into FERRARI and MAJOR I want to say several things:
Both tools are only available for download as compiled Java JAR archives.
So I wrote to the scientists who have created those tools today and asked them our question. As soon as I will receive an answer I will report back here.
Anyway, I have looked into FERRARI's architecture and think I may have found out how they do it.
So here is my educated guess (still untested) about what you could do:
Instrument your JDK classes.
Add one simple class BootstrapLock as described below.
Re-pack the instrumented + the new class into a modified rt.jar.
Write a little dummy Java agent as described below.
public class BootstrapLock {
private static volatile boolean inBootstrap = true;
public static boolean inBootstrap() {
return inBootstrap;
}
public static synchronized void setEndOfBS() {
inBootstrap = false;
}
}
public class DummyAgent {
public static void premain(String options, Instrumentation ins) {
BootstrapLock.setEndOfBS();
}
}
So basically the logic is as follows:
Agents are loaded before the main application class, but after bootstrapping.
Thus the very fact that the agent is active means that bootstrapping is finished.
Thus the agent can switch off the global marker inBootstrap.
Your instrumented classes can check the marker in order to determine if their additional instrumentation code should be bypassed or not.
I am unsure if I have enough time to test this anytime soon, but at least I wanted to post this answer here so maybe you, Vijai, can also look into it and provide some feedback. Four eyes see more than two...
Update: One of the FERRARI authors has answered my inquiry and confirmed my explanation above. You can just use a java agent as a marker of JVM having finished its bootstrapping. Maybe you do not even need the additional class, but just check if the agent has been loaded into the JVM yet. It would make things even simpler, I just do not know if it performs well. Just test it.
I am looking for a way to remove all uses of a particular class, including the class itself, at compile time. Basically a form of pre-processing, but I'd like to do it without having to surround all the instances with #ifdebug ... #endif.
Is there any ant-based tool out there that can do this? If not, can anyone point me in the right direction for how to write such a tool? (not a minor undertaking I know, but if its the only option...)
The situation is I have a helper class for debugging function calls. This is instantiated at the beginning of a function and a call is made at the end. This is a JavaME application so I'm nervous about the overhead this is adding to performance. I already have a release and debug build that have pre-processor directives using ProGuard, so I would like to exclude the use of this helper class from the release build. It doesn't appear this can be done with ProGuard.
"This is instantiated at the beginning of a function and a call is made at the end. "
If this is all over your code maybe you need to look at AOP.
or a state design pattern for the helper class, in test mode it does one thing but in prod it does another(like nothing)
Do you know that this debug code will make the JavaME app slow? You could also try creating a way to conditionally call these debug methods.
A few more ideas ... I've never written a JavaME app, but I assume there is way to run/test with running on the actual device. Given this way of running/testing, perhaps you can use Eclipse/Netbeans to debug your code and use proper breakpoints instead of programmatically tracing method calls. No harm to compiled code in this case. Also consider using AspectJ to trace method calls, this can be conditionally done after code is compiled since AspectJ alters bytecode directly (not sure how this plays with JavaME). Lastly, I've heard of people using the standard GNU C/C++ preprocessor on Java. I have no idea if it works, google will help you.
Not exactly what you want but...
You could separate your code to modules (core and debug, in your case), then make sure modules call each other via reflection: use an interface available in core, create a wrapper class in core that will hide object instantiation via reflection detail/
Then, on production, just omit the debug code and have the wrapper "do nothing" if the instantiation fail / when you set a specific flag.
This way your debug classes won't make it into production and you won't have to "statically link" to them so your core production code won't care.
Of course, this is only possible if your debug code has no side effects visible to core code, but it seems that's your case (from your problem description).
Is it possible to just create the class once, on application startup, instead of creating an instance for each method? Your debug class could then look like this:
public class Debug // maybe make this a *gasp* singleton?
{
public static void start(); // called at start of method
public static void end(); // called at end, probably should be in a finally block
public static void setDebugMode(boolean debugOn); // turn off for production mode
}
Set debug mode to "true" in testing but "false" in production. When debug mode is off, none of the methods do anything (except check the state of debug mode, of course).
You don't avoid the overhead of the function call, and you do need to check the state of that boolean, but you do get to avoid jumping through hoops trying to avoid load the class at all.
This will need more work if you have a multithreaded application, too.