java 调试

来源:互联网 发布:linux退出用户 编辑:程序博客网 时间:2024/05/22 13:04

使用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. 调试的基本思路( 分段调试 )

 

 

0 0