JavaSE6️⃣调试:断言&日志
1、断言
断言
Assertion
(Java 1.4+)在代码中的预置检查条件,用于确保代码在运行时满足特定条件。
1.1、语法
使用
assert
关键字,可指定断言失败后的异常信息,便于调试。
-
断言成功:表达式为
true
,程序正常运行。 -
断言失败:表达式为
false
,抛出AssertionError
异常。assert 表达式; assert 表达式 : "异常信息"; // 指定断言失败后的异常信息
示例(假设断言已启用)
public static void main(String[] args) {
int x = 10;
assert x >= 0; // ok
x = -10;
assert x >= 0; // 抛出 AssertionError 错误
}
1.2、启用断言
启用断言:Java 断言默认关闭,需要向 JVM 传递参数显式启用。
-enableassertions
(可简写-ea
)
-
指定类启用:向 JVM 传递参数 。
java -ea 类名.java # 示例:java -ea Main.java
-
指定包启用:指定包名,以三个
.
结尾。java -ea 包名... # 示例:java -ea indi.jaywee.user...
1.3、使用时机
Hint:启用断言会影响性能,且断言失败会导致程序异常结束。
- 开发/测试环境:可启用断言,方便程序调试。
- 生产环境:禁用断言以提高性能,使用以下机制。
- 异常处理机制:处理代码中的异常。
- 日志框架:将程序运行过程中的信息输出到日志中,便于排查和调试。
2、日志
日志(
Logging
)用于在应用程序中输出信息,方便调试、运维、监控等工作。
2.1、功能
日志框架通常提供以下功能。
作用 | |
---|---|
记录 | 输出日志信息 |
目标处理 | 将日志输出到不同位置,如控制台、文件、数据库等 |
格式化 | 自定义日志输出格式 |
级别 | 指定日志级别,如 SEVERE、WARNING、INFO、CONFIG、FINE、FINER、FINEST 等 |
过滤 | 按位置、级别等过滤日志 |
2.2、标准库
java.util.logging.Logger
Java SE 内置日志库。
- 日志级别:高于指定级别的日志才会输出
- 类型:
SEVERE
、WARNING
、INFO
、CONFIG
、FINE
、FINER
、FINEST
。 - 设置:使用
Logger.setLever()
设置日志级别(默认INFO
)。
- 类型:
- 支持添加处理器、过滤器、父类日志等功能。
示例
public class MyDemo {
public static void main(String[] args) {
Logger logger = Logger.getGlobal();
logger.warning("I'm warning!");
logger.info("I'm info!");
logger.fine("I'm fine!");
}
}
输出结果:
三月 07, 2023 3:47:50 下午 indi.jaywee.java.MyDemo main
警告: I'm warning!
三月 07, 2023 3:47:50 下午 indi.jaywee.java.MyDemo main
信息: I'm info!
2.3、第三方库(❗)
Java 标准库使用较麻烦,第三方日志库提供更强大的功能。
通常是采用日志门面 + 日志实现的方式。
日志门面:面向接口编程。支持接入多种日志框架,减少应用和具体日志框架的耦合性。
Commons Logging | SLF4J(👍) | |
---|---|---|
含义 | 简单的日志接口 | 简单日志门面(Simple Logging Facade for Java) |
提供者 | Apache | QOS.ch |
日志绑定方式 | (静态绑定)编译时 | (动态绑定)运行时,可在运行期间替换底层日志框架 |
性能 | - | 性能更好,兼容性更佳 |
日志实现:均由 Apache
提供,根据需要选择。
Log4j | Logback(👍) | |
---|---|---|
说明 | 功能强大,使用方便 | Log4j 改进版 |
线程安全 | 支持,但可能引起死锁 | 更稳定的多线程支持,允许在不同程序之间共享日志配置 |
异步日志 | 2.x 开始支持 | 支持 |
配置方式 | 文件(properties 或 xml ) |
文件(xml 或 groovy )、编程(Java、Spring Boot |
插件 | - | 更加丰富 |
生态圈 | 拥有更多用户、集成应用支持 | 更活跃的社区支持 |
说明 | 1.x 已淘汰,2.x 之后较少更新维护 |
持续更新发展中 |
过去主流是
Commons Logging + Log4j
,目前趋势是
SLF4J + Logback
。
2.3.1、日志门面
Commons Logging
特点
- 日志实现支持:自动发现类路径下可用的日志系统,按以下优先级。
Log4j
JDK Logging
LogKit
- 日志级别:
FATAL
:致命错误ERROR
:一般错误WARN
:警告信息INFO
:一般信息(默认)DEBUG
:调试信息TRACE
:详细跟踪信息
- 日志绑定:类装载时动态绑定。
org.apache.commons.logging
-
Log 接口:定义日志记录的方法。
-
LogFactory 类:用于获取 Log 实例。
public class Main { // 获取实例 private static final Log LOG = LogFactory.getLog(Main.class); public static void foo() { // 输出日志 LOG.info("foo"); } }
SLF4J
特点:更加灵活,性能更好。
- 日志实现支持:自动发现类路径下可用的日志系统,按以下优先级。
Log4j
Logback
(通常)JDK Logging
SimpleLogger
- 日志级别:支持 6 种日志级别,与
Commons Logging
相同。 - 日志绑定:编译时静态绑定,性能更好。
org.slf4j
-
Logger接口:定义日志记录的方法。
-
LoggerFactory 类:用于获取 Logger 实例。
public class Main { // 获取实例 private static final Logger LOGGER = LoggerFactory.getLogger(Main.class); public static void foo() { // 输出日志 LOGGER.info("foo"); } }
2.3.2、日志实现
Log4j:组件化设计的日志系统
主要组件:
-
Logger:记录日志信息。
-
Filter:过滤日志信息。
-
Layout:将日志信息转换为指定格式的字符串。
-
Appender:指定输出目的地。
┌────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────┐ │ Logger │───>│ Filter │───>│ Layout │───>│ Appender │───>│ 目的地 │ └────────┘ └──────────┘ └──────────┘ └──────────┘ └─────────┘
Logback:Log4j 的继承者
在 Log4j 功能的基础上,具有更高性能和更丰富的特性。