Frage

Ist es für den Compiler möglich, Anweisungen, die zu Debugzwecken (z. B. Protokollierung) verwendet werden, aus dem Produktionscode zu entfernen?Die Debug-Anweisungen müssten irgendwie markiert werden, vielleicht mithilfe von Anmerkungen.

Es ist einfach, eine Eigenschaft festzulegen (debug = true) und sie bei jeder Debug-Anweisung zu überprüfen, aber das kann die Leistung beeinträchtigen.Es wäre schön, wenn der Compiler die Debug-Anweisungen einfach verschwinden lassen würde.

War es hilfreich?

Lösung

Zwei Empfehlungen.

Erste:Verwenden Sie für eine echte Protokollierung ein modernes Protokollierungspaket wie log4j oder die in Java integrierte Protokollierung.Machen Sie sich nicht so viele Gedanken über die Leistung, die Überprüfung der Protokollierungsebene liegt in der Größenordnung von Nanosekunden.(es ist ein ganzzahliger Vergleich).

Und wenn Sie mehr als eine einzelne Protokollanweisung haben, schützen Sie den gesamten Block:

(log4j, zum Beispiel:)

if (logger.isDebugEnabled()) {

  // perform expensive operations
  // build string to log

  logger.debug("....");
}

Dies gibt Ihnen die zusätzliche Möglichkeit, die Protokollierung zur Laufzeit zu steuern.Es kann sehr umständlich sein, einen Debug-Build neu starten und ausführen zu müssen.

Zweite:

Du wirst vielleicht finden Behauptungen sind mehr, was Sie brauchen.Eine Behauptung ist eine Anweisung, die ein boolesches Ergebnis mit einer optionalen Meldung ergibt:

 assert (sky.state != FALLING) : "The sky is falling!";

Immer wenn die Behauptung zu „false“ führt, schlägt die Behauptung fehl und es wird ein AssertionError mit Ihrer Nachricht ausgegeben (dies ist eine ungeprüfte Ausnahme, die dazu gedacht ist, die Anwendung zu beenden).

Das Tolle daran ist, dass diese von der JVM besonders behandelt werden und zur Laufzeit mithilfe eines VM-Parameters auf Klassenebene umgeschaltet werden können (keine Neukompilierung erforderlich).Wenn die Option nicht aktiviert ist, entsteht kein Overhead.

Andere Tipps

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.");
        }
    }
}

Der Compiler wird den Codeblock mit "Hallo, Protokollierungswelt" entfernen. In IT ist Enable_logging auf true eingestellt, da es ein statischer Endwert ist.Wenn Sie einen Obfuscator wie Proguard verwenden, verschwindet auch die Config-Klasse.

Ein Obfuscator würde stattdessen auch Dinge wie diese zulassen:

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

Die Methode Log#log würde im Compiler auf nichts reduziert und vom Obfuscator zusammen mit allen Aufrufen dieser Methode und schließlich sogar der Log-Klasse selbst entfernt werden.

Eine andere Möglichkeit besteht darin, die if-Anweisung in Ihre Protokollierungsfunktion einzufügen. Auf diese Weise erhalten Sie weniger Code, allerdings auf Kosten einiger zusätzlicher Funktionsaufrufe.

Ich bin auch kein großer Fan davon, den Debug-Code komplett zu entfernen.Sobald Sie in der Produktion sind, benötigen Sie wahrscheinlich Zugriff auf Debug-Meldungen, falls etwas schief geht.Wenn Sie Ihr gesamtes Debugging auf Codeebene entfernen, ist dies nicht möglich.

Verwenden Java-Präprozessor?(google foo low, aber das ist ein Link zu den alten Joel-Foren, in denen darüber diskutiert wird)

Java enthält eine Art eigenen Präprozessor.Es heißt GEEIGNET.Es verarbeitet und generiert Code.Im Moment bin ich mir nicht sicher, wie das funktionieren soll (ich habe es nicht ausprobiert).Aber es scheint für solche Dinge verwendet zu werden.

Ich würde auch dringend empfehlen, ein Protokollierungsframework zu verwenden.

Der logger.IsDebugEnabled() Dies ist nicht zwingend erforderlich, es kann lediglich schneller sein, vor der Protokollierung zu überprüfen, ob sich das System im Debug-Level befindet.

Durch die Verwendung eines Protokollierungsframeworks können Sie Protokollierungsstufen im Handumdrehen konfigurieren, ohne die Anwendung neu starten zu müssen.

Sie könnten eine Protokollierung haben wie:

logger.error("Something bad happened")
logger.debug("Something bad happend with loads more detail")

Das "Trick„scheint Ihre Debug-Anweisungen verschwinden zu lassen

public static final boolean DEBUG = false;

if (DEBUG) { //disapeared on compilation }

Der Post sagte, dass javac ist schlau genug, das zu überprüfen static final boolean und schließen Sie die Debug-Anweisungen aus.(Ich habe es nicht persönlich ausprobiert)

Für die Protokollierung sehe ich persönlich keinen Code wie den folgenden:

if (logger.isDebugEnabled()) {
    logger.debug("....");
}
realImportantWork();

Die Protokollierung lenkt mich davon ab realImportantWork().Der richtige Weg für mich ist:

logger.debug("....");
realImportantWork()

plus die Konfiguration, die alle Debug-Meldungen in der Produktion ausschließt.

Ich meine, dass die logger.isDebugEnabled() Die Kontrolle sollte die Aufgabe des Protokollierungsframeworks sein, nicht meine Aufgabe.Die meisten Protokollierungsframeworks unterstützen Konzepte wie „Logger“, „LogLevel“.was den Zweck erfüllen kann.

Um Ihre Frage direkt zu beantworten:Ich weiß nicht.

Aber hier ist eine andere Lösung für Ihr Problem:Meiner Meinung nach gibt es hier zwei Aussagen, die miteinander kollidieren:„Debug-Anweisungen“ und „Produktionscode“.

Was ist der Zweck von Debug-Anweisungen?Helfen Sie dabei, Fehler beim (Unit-)Testen zu beseitigen.Wenn eine Software ordnungsgemäß getestet wurde und den Anforderungen entspricht, sind Debug-Anweisungen nichts anderes als VERALTET.

Ich bin strikt dagegen, irgendwelche Debug-Anweisungen im Produktionscode zu belassen.Ich wette, niemand macht sich die Mühe, Nebenwirkungen von Debug-Code im Produktionscode zu testen.Der Code tut wahrscheinlich, was er tun soll, aber macht er mehr als das?Funktionieren alle Ihre #defines korrekt und entfernen Sie wirklich den GESAMTEN Debug-Code?Wer analysiert 100.000 Zeilen vorverarbeiteten Codes, um zu sehen, ob der ganze Debug-Zeug weg ist?

Sofern wir keine andere Definition von Produktionscode haben, sollten Sie erwägen, die Debug-Anweisungen nach dem Testen des Codes zu entfernen und damit fertig zu sein.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top