java 調試


使用log

System.out.println() 有很大的不足之處, 當程序調試結束后, 將這個程序投入產品化時, 往往需要消除 System.out.println()的輸出, 這時候可能需要逐行掃描, 麻煩.

log4j 是一個功能強大, 簡單易用的日志工具, 因此 log4j 除了可用於輔助調試之外, 還可用於記錄程序的運行日志.  log4j 已經可以支持 c, c++, c#, perl, python 等等.

1. 下載和安裝 log4j

http://logging.apache.org/log4j/ 下載后解壓, 看到如下文件結構:

  • examples: 該文件夾下包含了 log4j 的一些使用范例.
  • site: 該文件夾下包含了 log4j 官方站點的相關頁面, 包括 log4j的API文檔
  • src: 該文件夾下包含了log4j 的源代碼.
  • tests: 該文件夾下包含了 log4j 的一些測試用例.
  • log4j-1.2.15.jar: 這個JAR包就是log4j項目的核心工具包.
  • 其他一些雜項文件.

最簡單的做法是將 log4j-1.2.15.jar 添加到系統的 CLASSPATH環境變量中, 以后即可在程序中使用 log4j日志工具包. 或者將log4j-1.2.15.jar核心類庫添加到應用的類的加載路徑里, 如WEB應用, 將 log4j-1.2.15.jar添加到WEB-INF/lib路徑下即可.

2. Logger

Logger 是 log4j 最重要一個組件, 它代表一個日志輸出器, 其功能有點類似 System.out的功能, 也就是說, 在程序中通過 Logger即可進行輸出, Logger比 System.out更強大的地方在於, 它可以自由的關閉部分一些調試信息的輸出, 而不影響其他人得調用.

為了讓 Logger 能關閉部分調試信息的輸出而不影響其他人, Logger必須對日志進行分類控制,  log4j 里 Logger 的分類是通過它的名字來控制的,Logger 的名字是一個區分大小寫的, 形如 org.crazyit.empsys.Manager 的字符串.

在程序中得到一個Logger非常簡單, Logger提供了如下兩個靜態方法來獲得 Logger對象.

  • static Logger getLogger(java.lang.Class clazz): 以clazz類的類名作為 Logger的名字創建Logger, 該方法的本質是 getLogger(clazz.getName())
  • static Logger getLogger(java.lang.String name): 創建一個名為 name 的 Logger 對象.

從上面介紹不難看出, Logger 的名字與 Java 包名的集成關系非常相似, 這一點是 log4j 故意設計的. 通過這種方式控制 Logger 之間的繼承關系, 例如 名為 org 的 Logger 是名為 org.crazyit的祖先

log4j 還提供了一個根(root) Logger, 它是所有 Logger 的祖先, 根具有兩個特征:

  • 根 Logger 總是存在的
  • 程序不能通過使用字符串名字得到根, 只能通過Logger的靜態方法 getRootLogger 來得到根.

得到對象之后, 可以通過 5 個方法執行輸出

  • public void debug(Object message, [Throwable t]): 以 debug 級別輸出 message 信息, 如果傳入了 t 參數, 還會輸出 t 的跟蹤棧信息.
  • public void info(Object message, [Throwable t]):
  • public void warn(Object message, [Throwable t]):
  • public void error(Object message, [Throwable t]):
  • public void fatal(Object message, [Throwable t]):

從上面可以看出, Logger 執行輸出時, 涉及到一個級別問題. log4j 為上面 5 個方法提供了 5 個對應的級別, 它們的優先級從低到高依次為: DEBUG<INFO<WARN<ERROR<FATAL

與此同時, log4j准許調用Logger的setLevel(Level level) 方法設置自身的級別, 例如: logger.setLevel(level.DEBUG);

log4j 制定了一個規則: 只有當Logger的輸出方法的級別高於或等於 Logger 本身的級別時, 這條輸出語句才會生成真正的輸出. 示例如下:

Logger logger = Logger.getLogger("com.foo");

logger.setLevel(Level.INFO);  // 設置 Logger 本身的優先級別 INFO

logger.warn("www.crazyit.org");  // 這條輸出語句生成輸出, 因為 WARN > INFO

logger.debug("www.cryzit.org");  // 這條輸出語句不會輸出, 因為 DEBUG < INFO

使用 Logger 輸出調試信息只要3隔步驟,

1) 調用 Logger 的 getLogger() 靜態方法返回一個 Logger對象

2) 使用 setLevel()方法設置 Logger的級別

3) 使用 Logger 的 debug(), info(), warn(), error(), fatal() 方法輸出信息.

如果程序每次都需要通過3個步驟來執行輸出, 那 log4j 只比 System.out 稍微靈活一點, 當程序需要關閉某批調試輸出時, 將它們對應的 Logger 的 level 設置的更高即可. 但是這樣也不很好.

為此, log4j 又制定了一個規則: 如果程序沒有為某個 Logger 顯示指定其 level, 它將繼承離它最近的祖先的 level.

程序無需為每個 Logger 顯示設置 level, 如果想控制一批 Logger 的信息輸出, 可以控制這批 Logger 的最頂層 Logger 的 level 即可.

為了便捷地控制每個類中得 Logger, 習慣上將每個 Logger的名稱設為與當前類的類名相同. 例如: Logger log = Logger.getLogger(EmpManager.class);

假如 EmpManager 類位於 org.crazyit.salary.service 包下, 那這個 Logger 的名字就是 org.crazyit.salary.service.EmpManager.

3. Appender 和 Layout

log4j 可以將日志輸出到各種設備, 例如控制台, 文件, GUI組件, 遠程 Socket 服務器 等, 而且可以將日志輸出到多個輸出設備中.

log4j 使用 Appender 來代表日志信息的輸出目的,

ConsoleAppender: 輸出到控制台

DailyRollingFileAppender: 輸出到文件的 Appender. 等等很多.

Logger 提供了一個 addAppender() 方法用於將指定 Appender 添加為與 Logger 關聯. 默認情況下, 每個Logger關聯的Appender是其所有祖先Logger關聯的Logger和它自己關聯的 Appender的總和.

Layout 是指輸出的式樣

HTMLLayout: 控制日志輸出成 HTML 格式的 Layout.

XMLLayout, PatternLayout(字符串),SimpleLayout(簡單日志信息)

4. 使用 log4j 輸出

實際開發中使用 log4j 時幾乎不會再 java 代碼中定義 Logger, Appender 和 Layout, 而通常都回采用配置文件來管理, log4j 准許以下兩種格式的配置文件.

Properties 屬性文件格式的配置文件, 通常配置文件名為 log4j.properties

xml 格式的配置文件, 通常配置文件名為 log4j.xml

不管使用那種文件, 配置的方法都是一樣的. 配置以下 3 個部分.

配置一個或多個 Logger, 這些 Logger 用於控制輸出

還需要配置一個或多個 Appender, Appender 代表日志的輸出設備, 配置 Appender 時需要制定使用的 Layout

將 Logger 和 一個或多個 Appender 進行關聯.

例如: log4j.xml

<?xml version="1.0" encoding="gdk" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
    <!-- 定義輸出到控制台的 Appender -->
    <appender name="stdout" class="org.apache.log4j.ConsoleAppender">
        <!-- 定義該 Appender 對應的 Layout -->
        <Layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern"
                        value="===CRAZYIT.ORG=== %r %d [%t] %-p %c %x - #%l# - %m%n"/>
        </layout>
    </appender>
<!-- 該logger將對 lee 包及其所有子包之內的 Logger 起作用 -->
<logger name="lee">
    <!-- 輸出 debug 及更高級別的日志 -->
    <level value=“debug”/>
    <!-- 將日志輸出到控制台 -->
    <appender-ref ref="stdout"/>
</logger>
<!-- 制定日志級別, 引用那些 Appender -->
<root>
    <!-- 輸出 info 及其更高級別的日志 -->
    <level value="info"/>
    <appender-ref ref="stdout"/>
</root>
</log4j:configuration>

然后就可以在程序中直接使用 logger.debug("開始執行程序");

其他方法

1. 利用編譯器的提示信息

2. 跟蹤程序的執行流程

3. 斷點調試 ( IDE 提供, 比如 eclipse )

4. 隔離調試 (將一部分代碼注釋掉)

5. 調試的基本思路( 分段調試 )

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM