调试器是 Eclipse 、 NetBeans 这类专业集成开发环境的一部分 。 在启动调试器之前, 本节先给出一些有价值的建议 。
1 ) 可以用下面的方法打印或记录任意变量的值 :

System.out.println("x=" + x);
// 或者
Logger.getGlobal().info("x=" + x)

2 ) 一个不太为人所知但却非常有效的技巧是在每一个类中放置一个单独的 main 方法 。这样就可以对每一个类进行单元测试 。

public class MyClass
{methods and fields...public static void main ( String[] args){test code}
}

3) 使用单元测试框架例如 JUnit

4) 日志代理(logging proxy)是一个子类对象,他可以截获方法按调用,并进行日志记录,然后调用超类中的方法。例如,如果在调用 Random 类的 nextDouble 方法时出现了问题,就可以按照下面的方式,以匿名子类实例的形式创建一个代理对象:

    public static void main(String[] args){Random generator = new Random(){@Overridepublic double nextDouble() {double result = super.nextDouble();Logger.getGlobal().info("nextDouble: " + result);return result;}};System.out.println(generator.nextDouble());}

当调用 nextDouble 方法时 , 就会产生一个日志消息 。 要想知道谁调用了这个方法, 就要生成一个堆栈轨迹 。

运行结果:

5. 利用 Throwable 类提供的 pringStackTrace 方法,可以从任何一个异常对象中获得堆栈情况。下面的代码将捕获任何异常,打印异常对象和堆栈轨迹,然后,重新抛出异常,以便能够找到相应的处理器。

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

不一定要通过捕获异常来生成堆栈轨迹。只要在代码的任何位置插入下面这条语句就可以获得堆栈轨迹:

Thread.dumpStack();

6) 一般来说,堆栈轨迹显示在 System.err 上。也可以利用printStackTrace(PrintWriter s)方法将它发送到一个文件中。另外,如果想记录或者显示堆栈轨迹,就可以采用下面的方式,将它捕获到一个字符串中:

StringWriter out = new StringWriter();
new Throwable().printStackTrace(new PrintWriter(out));
String description = out.toString;

7) 通常,将一个程序的错误信息保存在一个文件中是非常有用的。然而,错误信息被送到 System.err 中,而不是 System.out 中。因此,不能够通过运行下面的语句获取它们:

java MyProgram > errors.txt    // 这里只是将标注输出【即 System.out】内容重定向到 errors.txt 中
// 正确的做法是
java MyProgram 2> errors.txt    // 这里就是将标准出错【即 System.out】 内容重定向到 errors.txt// 要想在同一个文件中同时捕获 System.out 和 System.err,需要这样做
java MyProgram 1> errors.txt 2>&1    // 1> errors.txt 表示将 System.out 重定向到 errors.txt;2>&1 表示将 System.err 重定向到 System.out 中// 上述命令将在bash 和 windows shell 中运行
// PS: 操作系统一般都有这三个三个I/O,分别是标准输入、标准输出、标准出错。分别对应Java中的 System.in System.out System.err
// “>" 重定向符号 ">>" 可以追加的重定向

8) 让非捕获异常[即运行时异常 RuntimeException,非检查异常]的栈轨迹出现在 System.err 中并不是一个很理想的方法。如果在客户端偶然看到这些消息,则会感到迷惑,而且在需要的时候也无法实现诊断目的。比较好的方式是将这些内容记录到一个文件中。keyi调用静态的 Thread.setDefaultUncaughtExceptionHandler 方法改变非捕获异常的处理器。

new Thread.UncaughtExceptionHandler(){@Overridepublic void uncaughtException(Thread t, Throwable e) {// save information in log fileLogger.getGlobal().throwing("com.mycompany.myapp", "main", e);}
}

9) 要想观察类的加载过程,可以用 -verbose 标志启动 Java 虚拟机。这样就可以看到如下所出书结果:

有时候 , 这种方法有助于诊断由于类路径引发的问题 。

10 ) -Xlint 选项告诉编译器对一些普遍容易出现的代码问题进行检査 。 例如 , 如果使用下面这条命令编译 :
javac -Xlint : fallthrough
当 switch 语句中缺少 break 语句时 , 编译器就会给出报告(术语 “ lint ” 最初用来描述一种定位 C 程序中潜在问题的工具 , 现在通常用于描述查找可疑但不违背语法规则的代码问题的工具 。 )

下面列出了可以使用的选项 :

11) java 虚拟机增加了对 Java 应用程序进行监控 (monitoring ) 和管理 ( management ) 的支持 。 它允许利用虚拟机中的代理装置跟踪内存消耗 、 线程使用 、 类加载等情况 。 这个功能对于像应用程序服务器这样大型的 、 长时间运行的 Java 程序来说特别重要 。 下面是一个能够展示这种功能的例子 : JDK 加载了一个称为 jconsole 的图形工具 , 可以用于显示虚拟机性能的统计结果, 如图 7 -3 所示 。 找出运行虚拟机的操作系统进程的 ID 。 在 UNIX / Linux 环境下 ,运行 ps 实用工具, 在 Windows 环境下, 使用任务管理器 。 然后运行 jconsole 程序 :

jconsole processID【即进程ID】

控制台给出了有关运行程序的大量信息 。有关更加详细的信息参见 www.orade.com/technetwork/articles/java/jconsole-1564139.html

12) 可以使用 jmap 实用工具获得一个堆的转储 , 其中显示了堆中的每个对象 。 使用命令如下 :

jmap -dump:format=b,file=dumpFileName processID
jhat dumpFileName

然后 , 通过浏览器进人localhost:7000 , 将会运行一个网络应用程序 , 借此探查转储对象时堆的内容 。

13 ) 如果使用 -Xprof 标志运行 Java 虚拟机, 就会运行一个基本的剖析器来跟踪那些代码中经常被调用的方法 。 剖析信息将发送给 System . out 。 输出结果中还会显示哪些方法是由即时编译器编译的 。

《Java 核心技术卷1 第10版》学习笔记------调试技巧相关推荐

  1. Java 核心技术卷 II(第 8 版) – 读书笔记 – 第 1 章(下)

    22.一旦获得了一个 Charset,就可以在 Java 的 Unicode 和指定的编码格式之间进行转化,下面以 GBK 和 Unicode 之间做为例子. 从 Unicode 到 GBK: imp ...

  2. 《Java 核心技术卷1 第10版》学习笔记------异常

    异常处理的任务就是将控制权从错误产生的地方转移给能够处理这种情况的错误处理器 . 7.1.1 异常分类 在 Java 程序设计语言中, 异常对象都是派生于 Throwable 类的一个实例 . 稍后还 ...

  3. 《Java 核心技术卷1 第10版》学习笔记------对象克隆【对象拷贝】

    由于克隆并不太常见,而且有关的细节技术性很强,你可能只是想稍做了解,等真正需要时再深人学习. 先来回忆为一个包含对象引用的变量建立副本时会发生什么 .原变量和副本都是同一个对象的引用: Employe ...

  4. 《Java 核心技术卷1 第10版》学习笔记 ------ 泛型【进阶】

    这部分主要是结合 Java 虚拟机实现泛型的原理进一步研究如何更好的使用泛型. 8.5 泛型代码和虚拟机 虚拟机没有泛型类型对象---所有对象都属于普通类.所以编译器在编译的时候会进行类型擦除操作. ...

  5. 《Java 核心技术卷1 第10版》学习笔记 ------ 泛型【基础】

    泛型从Java SE 5.0 中开始出现,是 Java 程序设计语言从 1.0 版本发布以来,变化最大的部分. 使用泛型机制编写的程序代码要比那些杂乱地使用 Object 变量,然后再进行强制类型转换 ...

  6. 《Java 核心技术卷1 第10版》学习笔记------日志

    日志 API 的优点: 可以很容易地取消全部日志记录, 或者仅仅取消某个级别的日志, 而且打开和关闭这个操作也很容易 . 可以很简单地禁止日志记录的输出, 因此, 将这些日志代码留在程序中的开销很小 ...

  7. 《Java 核心技术卷1 第10版》学习笔记------ 接口(Interface)

    接口技术作用:主要描述类具有什么功能,而并不给出每个功能的是的实现. Java的继承(inheritance)是不支持的多继承的,但是Java接口是支持多继承的. 一个 Java 类实现一个接口类就必 ...

  8. 《Java 核心技术卷1 第10版》学习笔记------ 对象包装器、自动装箱、拆箱

    有时, 需要将 int 这样的基本类型转换为对象. 所有的基本类型都冇一个与之对应的类.例如,Integer 类对应基本类型 int.通常, 这些类称为包装器 ( wrapper ) 这些对象包装器类 ...

  9. 《Java 核心技术卷1 第10版》学习笔记------ Object类的 hashCode 方法

    散列码( hash code ) 是由对象导出的一个整型值.散列码是没有规律的.如果 x 和 y 是两个不同的对象, x.hashCode( ) 与 y.hashCode( ) 基本上不会相同. 在表 ...

最新文章

  1. 第十六讲 循环遍历文件和元组
  2. TensorRT推理报错:pycuda._driver.LogicError: cuMemcpyHtoDAsync failed: invalid argument
  3. CSS基础——position位置属性
  4. mac下php mysql数据库文件怎么打开_Mac环境下php操作mysql数据库的方法分享
  5. 外媒:谷歌攻击码由中国作者发布
  6. codeforces1467 E. Distinctive Roots in a Tree(树上差分)
  7. java restsharp_C# RestSharp应用
  8. 玩转 SpringBoot 2 之整合 JWT 上篇
  9. 助力春运 重庆机场今晨新增一架飞机入列
  10. SQL Server数据库导入导出数据方式比较
  11. 本博已停用,现在的博客是www.mutousay.com
  12. Android【报错】Failed to resolve: com.android.support:appcompat-v7:28.0.0-alpha【报错】
  13. android接支付宝授权和支付功能
  14. Houdini 地形知识点
  15. 线面图标设计样式解析
  16. 5G NR MIB详解
  17. 前端学习之html特殊符号
  18. STM32固件库点灯
  19. anaconda无法安装最新版pip
  20. Epson机械手简单实例编程

热门文章

  1. 二、华为云ModelArts零代码实现美食分类识别
  2. 十八、深入Java 访问修饰符和非访问修饰符
  3. Java100例题(一)
  4. 三十、开始前端Vue.js的学习之路
  5. keras从入门到放弃(二十一)LSTM处理 RNN文本分类
  6. java定时调度main方法_java相关:Spring中实现定时调度的几种方法
  7. 字节跳动 2019 ICME 双赛道冠军团队方案分享
  8. 论文共读 | “阳奉阴违”的半监督学习算法 - Virtual Adversarial Training
  9. php实现上传文件功能,简单实现php上传文件功能
  10. js md5加密脚本