当前位置 : 主页 > 编程语言 > java >

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明

来源:互联网 收集:自由互联 发布时间:2022-07-14
11.5.8 日志记录说明 (1) 自定义日志记录器 private static final Logger logger = Logger . getLogger ( "包名全名" ); 个人见解,习惯就最好,定义一个全局的Logger,然后全局都用一个 Logger 也挺好,方便


 11.5.8  日志记录说明

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_配置文件

 (1) 自定义日志记录器

private static final Logger logger = Logger.getLogger("包名全名");

个人见解,习惯就最好,定义一个全局的Logger,然后全局都用一个 Logger 也挺好,方便;方便和准确按习惯选择一种就可以了

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_ide_02

 (2) 自定义默认配置

加载合适的自定义配置文件,后续更加方便使用

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_idea_03

 (3) 日志级别定义

对于需要的公共内容,直接写到 INFO/WARNING/SERVERE 级别上,其他程序员需要内容,可放在其他级别,方便正式环境的情况屏蔽他们

package com.dyy.jdk8;

import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.util.logging.*;

public class Main {
public static final String myPackage = "com.dyy.jdk8";;
public static void main(String[] args) throws IOException {
Main solution = new Main();
try{
Logger.getLogger(myPackage).setLevel(Level.ALL);
final int LOG_ROTATION_COUNT = 10;
Handler handler = new FileHandler("%h/LoggingImageViewer.log",0,LOG_ROTATION_COUNT);
Logger.getLogger(myPackage).addHandler(handler);
}catch (IOException e){
Logger.getLogger(myPackage).log(Level.SEVERE, "Can't create log file handler",e);
}

EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
Handler windowHandler = new WindowHandler();
windowHandler.setLevel(Level.ALL);
Logger.getLogger(myPackage).addHandler(windowHandler);

JFrame frame = new ImageViewFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Logger.getLogger(myPackage).fine("Showing frame");
frame.setVisible(true);
}
});
}
}

class ImageViewFrame extends JFrame {
private JButton button;
private static Logger logger = Logger.getLogger(Main.myPackage);
private static final int W = 600;
private static final int H = 600;
public ImageViewFrame(){
logger.entering("ImageViewerFrame","<init>");
setTitle("LoggingImageViewer");
setSize(W,H);

JMenuBar menuBar = new JMenuBar();
setJMenuBar(menuBar);

JMenu menu = new JMenu("File");
menuBar.add(menu);

JMenuItem openItem = new JMenuItem("Open");
menu.add(openItem);
openItem.addActionListener(new FileOpenListener());

JMenuItem exitItem = new JMenuItem("Exit");
menu.add(exitItem);
exitItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
logger.fine("Exiting.");
System.exit(0);
}
});

button = new JButton();
add(button,BorderLayout.CENTER);
button.setBackground(Color.WHITE);
logger.exiting("ImageViewerFrame","<init>");
}

private class FileOpenListener implements ActionListener{
@Override
public void actionPerformed(ActionEvent event) {
logger.entering("ImageViewFrame.FileOpenListener","actionPerformed",event);

JFileChooser chooser = new JFileChooser();
chooser.setCurrentDirectory(new File("."));
chooser.setFileFilter(new FileFilter() {
@Override
public boolean accept(File f) {
return f.getName().toLowerCase().endsWith(".gif") || f.isDirectory();
}

@Override
public String getDescription() {
return "GIF Images";
}
});

int r = chooser.showOpenDialog(ImageViewFrame.this);
if(r == JFileChooser.APPROVE_OPTION){
String name = chooser.getSelectedFile().getPath();
logger.log(Level.FINE, "Reading file {0}",name);
button.setIcon(new ImageIcon(name));
}else{
logger.fine("File open dialog canceled.");
}
logger.exiting("ImageViewerFrame.FileOpenListener", "actionPerformed");
}
}
}

class WindowHandler extends StreamHandler{
public void publish(LogRecord record){
super.publish(record);
flush();
}
}


最终还是用了配置文件,因为不用配置文件显示不出日志(可能作者是改了源文件?)

-Djava.util.logging.config.file=D:\program\test\testJ8\logging.properties

操作步骤:

  • 《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_ide_04

  • 点击:File->Open代开GIF源文件
  • 《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_java_05

  • 关闭GIF,查看日志

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_java_06

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_idea_07

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_java_08

 11.6 调试技术

调试建议:

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_ide_09

 (1)使用以下方式记录 变量 值

System.out.println(String.valueOf(a));


或者:

Logger.getGlobal().info(String.valueOf(a));


(个人建议:算法题用第1种,项目用第2种)

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_idea_10

 (2)需要调试的类中放 main 方法,方便测试和提供 case

个人建议:非 spring boot 可用【挺方便的】; spring boot 慎用,spring boot 多 main 会找不到启动类,或者用完屏蔽掉。

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_配置文件_11

 (3)使用 JUnit

这个东西确实挺好用的,适用于大型项目,小型的写写 log, main 足够了。

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_ide_12

 (4)日志代理

调用父类方法并进行输出

Logger.getGlobal().info(super.xx());


《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_java_13

 (5) 抛出前使用此方法进行日志输出:t.printStackTrace()

try{}catch(Throwable e){
e.printStackTrace();
throw e;
}


非异常行为的堆栈追踪(其实就是建立了一个异常来输出堆栈。。。)

Thread.dumpStack();


《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_配置文件_14

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_配置文件_15

 (6) 堆栈追踪可以传一个输出的处理流,在期望的位置输出异常

public class Main {
public static void main(String[] args) throws IOException {
Main solution = new Main();
int[] arr = new int[3];
try{
for(int i = 0; i <= 3; i++){
arr[i]=i;
}

}catch (Exception e){
e.printStackTrace(System.out);
}

}
}


比如这段代码是改成使用输出流输出异常,此时字是白色的:

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_配置文件_16

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_ide_17

 (7)使用输出符号执行 java 命令,将执行结果、异常输出到文件

测试代码:

public class Main {
public static void main(String[] args) throws IOException {
Main solution = new Main();
int[] arr = new int[3];
try{
for(int i = 0; i <= 3; i++){
arr[i]=i;
}

}catch (Exception e){
e.printStackTrace(System.out);
}

}
}


System.out 输出到文件:

java com.dyy.jdk8.Main > info.txt


《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_idea_18

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_ide_19

System.error 输出到文件:

java com.dyy.jdk8.Main > error.txt


《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_idea_20

输出:

测试方法1:

java com.dyy.jdk8.Main error.txt 2>&1


此方法仅输出,不会输出到文件(Linux和windows效果相同)

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_idea_21

输入到同一个文件:

java com.dyy.jdk8.Main >& error.txt


Linux 成功

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_java_22

 Windows 失败

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_idea_23

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_java_24

 (8)未捕获异常的统一处理

使用:Thread.setDefaultUncaughtExceptionHandler() 捕获所有未捕获异常(会导致程序崩溃的异常)

package com.dyy.jdk8;

import com.dyy.jdk8.test.ErrorUtil;
import java.io.*;
import java.util.logging.*;

public class Main {
public static void main(String[] args) throws IOException {
Main solution = new Main();
int[] arr = new int[3];

Logger logger = Logger.getLogger("com.dyy.jdk8");
FileHandler handler
= new FileHandler("logs.txt");
handler.setFormatter(new SimpleFormatter());
logger.addHandler(handler);

Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
logger.severe(ErrorUtil.exceptionStr((Exception) e));
}
});

for(int i = 0; i <= 3; i++){
arr[i]=i;
}

}
}


这里用了我的大招 ErrorUtil, 为了方便大家看,再贴一次:

package com.dyy.jdk8.test;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ErrorUtil {
public static String exceptionStr(Exception e, int length) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
e.printStackTrace(new PrintStream(baos));
String exception = baos.toString();

String regEx = "Caused by:(.*)";
Pattern pat = Pattern.compile(regEx);
Matcher mat = pat.matcher(exception);
boolean rs = mat.find();
if (rs) {
if (mat.group(1).length() > length) {
return mat.group(1).substring(0, length);
} else {
return mat.group(1);
}
} else {
if (exception.length() > length) {
return exception.substring(0, length);
} else {
return exception;
}
}
}

public static String exceptionStr(Exception e){
return exceptionStr(e,800);
}

public static String getAllException(Exception e){
ByteArrayOutputStream baos = new ByteArrayOutputStream();
e.printStackTrace(new PrintStream(baos));
String exception = baos.toString();
String regEx = "Caused by:(.*)";
Pattern pat = Pattern.compile(regEx);
Matcher mat = pat.matcher(exception);
boolean rs = mat.find();
if (rs) {
return mat.group(1);
} else {
return exception;
}
}
}

效果:

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_ide_25

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_java_26

 (9)通过 -verbose 标志观察 Java 虚拟机启动过程

比较适合新代码启动就崩溃的情况查原因

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_配置文件_27

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_配置文件_28

 (10) CTRL+SHIFT+F1 可打印层次组件结构(比如刚刚那个弹gif的例子)

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_配置文件_29

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_ide_30

 (11)Swing 调试器

设置双重缓冲,可以看到绘制时会不断进行红色闪烁:

RepaintManager.currentManager(getRootPane()).setDoubleBufferingEnabled(false);
((JComponent) getContentPane()).setDebugGraphicsOptions(DebugGraphics.FLASH_OPTION);


《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_ide_31

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_idea_32

 (12)使用 JDK 5 的 -Xlint 选项

通常用 -all 就可以:

javac -Xlint:all com.dyy.jdk8.Main

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_ide_33

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_java_34

 (13)使用 jconsole

这个通常先用 jps -l 查端口(有时候太长 jconsole 看不全)

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_idea_35

双击打开jdk/bin/jconsole.exe

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_配置文件_36

打开对应行

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_配置文件_37

可以查看各种信息,比如说对应日志配置的位置 VM 概要-> java.util.logging.config.file

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_idea_38

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_idea_39

 (14)jmap jhat 分析堆

jmap -dump:format=b,file=a.prof 19908


jmap 用来产生一个堆分析文件

jhat a.prof


jhat 用来分析堆(太多会卡死,实际大型的也不会用这个。。。)

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_idea_40

此处生成的端口是 7000(注意是自动的), 打开 ​​http://localhost:7000​​

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_java_41

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_ide_42

通过这部分查看堆的占用情况

13、14 这部分工具问题,可以查看我的另外一篇文章:《深入理解Java虚拟机》第4章 虚拟机性能监控与故障处理工具-看看虚拟机工具用起来有多简单

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_配置文件_43

 (15)配置参数 -Xprof  使用解析器

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_idea_44

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_idea_45

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试(8)日志记录说明+调试建议_ide_46

相关内容:选择 《Java核心技术 卷1》查找相关笔记

评论

网友评论