如果您的 Java 代码似乎存在导致运行缓慢的瓶颈,您需要“分析”代码。因此,您有几种选择。
JProfiler
JProfiler是一个商业程序,但您可以评估试用版。
高级教授
使用HPROF,Sun的Java从1.5版本开始就包含了一个探查器。
VisualVM
使用VisualVM(可以在here中找到教程),它是HPROF的图形替代方案。
另请参阅Rejeev Divakaran’s detailed instructions on memory profiling with VisualVM。
O配置文件
如果您使用的是 Linux,则可以使用 OProfile,这是一款低开销分析器,它使用内核模块来最大程度地减少其影响。
您需要recompile OProfile来获得Java支持(至少在Ubuntu上,没有带有Java支持的预编译OProfile包)。在Linux上,您可以使用以下shell脚本来编译和安装它:
sudo apt-get install libpopt-dev binutils-dev checkinstall &&
git clone git://oprofile.git.sourceforge.net/gitroot/oprofile/oprofile &&
cd oprofile &&
./autogen.sh &&
./configure --with-kernel-support \
--with-java=/path/to/fiji/java/linux-amd64/jdk1.6.0_24/ &&
make &&
sudo checkinstall
您应该确保 JDK 的路径正确。(但是您不需要使用 checkinstall,但是一旦您不再需要该木质,它可以让您轻松删除该木质。)
启动分析器
sudo opcontrol --start --no-vmlinux
最新版本的 OProfile 要求在启动 OProfile 守护程序之前具有默认组 oprofile 的用户帐户 oprofile。在当前的 Ubuntu 系统上,您通过调用 sudo adduser oprofile 可以来创建一个(Ubuntu 为每个新用户帐户存在一个同名的默认组)。如果您没有这样的帐户,您将在报告中看到类似的 anon (tgid:10014) range:0x100000-0x103000) 的内容。
启动斐济并支持分析
fiji -agentpath:/usr/local/lib/oprofile/libjvmti_oprofile.so --
停止分析器
sudo opcontrol --stop
获取分析数据
sudo opcontrol --dump &&
opreport -l image:\*/fiji
如果您得到类似 “anon (tgid:10014 range:0x100000-0x103000) 的边界,您可能在没有在组 oprofile 中创建用户帐户 oprofile 之前启动 OProfile 守护程序。
要获取有关源文件和行号的信息,包含 -g 选项提交给 opreport。
进一步阅读
相关详细信息,请参见第OProfile manual。
鲨鱼(适用于 macOS)
如果您使用的是 macOS,您可能会发现Shark 4很有用。
内存分析
即使Java的内存管理防止了大多数内存问题(未读取可以写入、访问未初始化/已释放的内存),也有可能发生内存泄漏:随着时间的推移,对象不断累积,很可能是因为对它们的引用过时。
注意:堆 是 Java 中“内存”的意思。
基于Javassist
一种非常通用的方法是使用(并可能修改)fiji-compat.jar 中的类imagej-legacy。
该内存分析器检测所有方法入口并使用 javassist 存在。在每次退出时,它都会报告相对内存使用情况、总内存使用情况以及当前方法的退出点。像这样称呼它:
./fiji --main-class fiji.MemoryProfiler fiji.Main
由于同步输出到 stderr,内存分析会明显减慢执行速度,因此您可能需要通过将环境变量 MEMORY_PROFILE_ONLY 设置为以空格分隔的类列表来限制要检测的类。
如果您想检测fiji.MemoryProfiler处理的任何类别,则需要使用极其复杂的命令行:
./fiji -Dpatch.ij1=false --cp jars/javassist.jar --cp jars/fiji-compat.jar \
--cp jars/ij.jar --main-class fiji.MemoryProfiler -- ij.ImageJ
使用 JVisualVM
JDK6 及更新版本附带了一个非常有用的工具,称为 jvisualvm。它位于 Java 开发工具包的 bin/ 目录中(它不附带 JRE,也称为 Java 运行时环境)。
JVisualVM 允许您附加到任何本地 Java 进程并检查状态。内存分析最有用的部分是 Monitor 选项卡中的 Memory 部分,总体堆转储使用情况(您还可以在其中创建堆转储,生成可左侧的对象及其引用列表),以及显示 Sampler 选项卡上的 Memory 按钮,该按钮打开一种实时版本的堆转储。
查看堆转储时,请确保单击顶行中的 Classes 按钮。这会显示当前在 Java 虚拟机中引用了实例的类的列表。左侧类名称将打开该类实例的详细列表,当单击该列表中的某个时,右上面板将显示该实例的字段,而右下面板将显示该特定实例的引用的对象。
注意:JVisualVM 永远不会停止它所附加的虚拟机,因此,如果您遇到的问题是时间敏感的,您一定希望在代码中加入权宜之计,以便能够仔细查看问题。