Using the Java Optimizer to Remove Debug Code

Abusing behavior of the the Java optimizer to remove debug code at runtime
🪦 End of Life. This note is no longer maintained, and is scheduled for deletion.

Debug log output can be high intrusive to source code, and even if not enabled, can impact performance. Real-Logic's Artio FIX server includes a debug feature that is stripped by the Java Optimizer at runtime if not enabled, resulting in zero impact when not being run in debug mode.

Artio achieves this by using static methods for logging that include a value that remains fixed at runtime, allowing the optimizer to elide the code if resulting in dead code. The key code from DebugLogger is listed below - the per tag output has been removed to simplify the code.

public static void log(final String content)
    if (isEnabled())
        //now actually log the data

The isEnabled method is a static method that returns a boolean value that is fixed at runtime.

public static boolean isEnabled()

And the DEBUG_PRINT_MESSAGES is held within a CommonConfiguration object:

public static final boolean DEBUG_PRINT_MESSAGES;

And finally, the value for DEBUG_PRINT_MESSAGES is set via a static initializer block of the CommonConfiguration object:

    final String debugPrintMessagesValue = getProperty(DEBUG_PRINT_MESSAGES_PROPERTY);
    boolean debugPrintMessages = false;
    if ("true".equals(debugPrintMessagesValue))
        debugPrintMessages = true;
        debugPrintMessages = false;
    DEBUG_PRINT_MESSAGES = debugPrintMessages;

When code needs to call the DebugLogger, all it does is:

DebugLogger.log("debug log message");

This is relying on the Java Optimizer to elide the code if not enabled. There is no official contract that says that you can rely on a JVM to actually do this for you, however it does work in practice with Azul and OpenJDK builds. If you rely on this feature, make sure to verify it works as expected on your environment.

An alterative approach to debug logging with minimal performance impact is found in Real-Logic's Aeron project. In that case, they make use of a Java agent which alters the byte code to add in debug statements at runtime. Without the agent running, there is no debug code overhead.


Change log

  • Added 18 December 2021
reading time
2 min read
last updated
review policy
--- Views

© 2009-2023 Shaun Laurens. All Rights Reserved.