由于对Java程序作性能测试,往往要分析gclog。
一般使用的工具为gcviewer。
但是想把gcviewer显示的结果截图到文档中又显得很不好看。
所以利用gcviewer里读取gclog的部分代码作了个,将gclog信息输出到csv文件的工具。
以便用Excel将csv打开,用Excel做出自己想要的gclog分析的图来。
关键代码
BufferedInputStream in = new BufferedInputStream(new FileInputStream(new File( gclog文件路径)));
final DataReader reader = factory.getDataReader(in);
final GCModel model = reader.read();
for (Iterator i = model.getGCEvents(); i.hasNext();) {
GCEvent event = (GCEvent) i.next();
StringBuffer sb = new StringBuffer();
event.toStringBuffer(sb);
System.out.println(sb.toString());
}
完整代码
需要gcviewer-x.xx.jar 如:gcviewer-1.29.jar
GCLogToCSV.java
package cn.pl.gclog2csv;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import com.tagtraum.perf.gcviewer.DataReader;
import com.tagtraum.perf.gcviewer.DataReaderFactory;
import com.tagtraum.perf.gcviewer.GCEvent;
import com.tagtraum.perf.gcviewer.GCModel;
public class GCLogToCSV {
private Env env;
private static final DataReaderFactory factory = new DataReaderFactory();
public GCLogToCSV(String[] args) {
env = analyseParameter(args);
}
public void excute() {
if (env == null) {
printUsage();
return;
}
// final GCViewer viewer = new GCViewer();
// viewer.setVisible(false);
InputStream in = null;
PrintWriter heapOut = null;
PrintWriter newOut = null;
PrintWriter oldPermOut = null;
SimpleDateFormat sdf = new SimpleDateFormat(
"yyyy/MM/dd HH:mm:ss");
try {
heapOut = new PrintWriter(new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream(new File(env.getOutputHeapCSV())))));
newOut = new PrintWriter(new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream(new File(env.getOutputNewCSV())))));
oldPermOut = new PrintWriter(new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream(new File(env.getOutputOldPermCSV())))));
in = new BufferedInputStream(new FileInputStream(new File(env.getInputGCLogPath())));
final DataReader reader = factory.getDataReader(in);
final GCModel model = reader.read();
in.close();
in = null;
writeHeader(heapOut, newOut, oldPermOut);
GCInfo heapInfo = new GCInfo();
GCInfo newInfo = new GCInfo();
GCInfo oldInfo = new GCInfo();
GCInfo permInfo = new GCInfo();
String type;
long offset = 0;
if (env.getStartTime() != null) {
offset = env.getStartTime().getTime();
}
String timpstamp;
boolean getInfoRet;
for (Iterator i = model.getGCEvents(); i.hasNext();) {
GCEvent event = (GCEvent) i.next();
getInfoRet = false;
type = event.getType().toString();
if (offset == 0) {
timpstamp = String.valueOf(event.getTimestamp());
} else {
timpstamp = sdf.format(new Date(offset + (long)(event.getTimestamp() * 1000)));
}
if (GCEvent.Type.GC.toString().equals(type)) {
getInfoRet = getGCInfo(event, newInfo, GCEvent.Type.DEF_NEW.toString());
if (getInfoRet) {
//timestamp,used_newsize,newsize,pausetime
newOut.printf("%s,%s,%s,%s\n",
timpstamp, newInfo.postUsed, newInfo.total, newInfo.pause);
}
getInfoRet = getGCInfo(event, heapInfo, null);
} else if (GCEvent.Type.FULL_GC.toString().equals(type)) {
getInfoRet = getGCInfo(event, oldInfo, GCEvent.Type.TENURED.toString());
if (getInfoRet && getGCInfo(event, permInfo, GCEvent.Type.PERM.toString())) {
//timestamp,used_oldsize,oldsize,old_pausetime,used_termsize,termsize,term_pausetime
oldPermOut.printf("%s,%s,%s,%s,%s,%s,%s\n", timpstamp,
oldInfo.postUsed, oldInfo.total, oldInfo.pause,
permInfo.postUsed, permInfo.total, permInfo.pause);
}
getInfoRet = getGCInfo(event, heapInfo, null);
}
if (getInfoRet) {
//timestamp,used_heapsize,heapsize,pausetime,gc_type
heapOut.printf("%s,%s,%s,%s,%s\n",
timpstamp, heapInfo.postUsed, heapInfo.total, heapInfo.pause, type);
}
//StringBuffer sb = new StringBuffer();
//event.toStringBuffer(sb);
//System.out.println(sb.toString());
}
System.out.println("execute done.");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (heapOut != null) {
heapOut.close();
}
if (newOut != null) {
newOut.close();
}
if (oldPermOut != null) {
oldPermOut.close();
}
if (in != null) {
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void writeHeader(PrintWriter heapOut, PrintWriter newOut, PrintWriter oldPermOut) {
heapOut.println("timestamp,used_heapsize,heapsize,pausetime,gc_type");
newOut.println("timestamp,used_newsize,newsize,pausetime");
oldPermOut.println("timestamp,used_oldsize,oldsize,old_pausetime,used_termsize,termsize,term_pausetime");
}
private Env analyseParameter(String[] args) {
Env ret = new Env();
String value;
for (int i = 0; i < args.length; i++) {
if ("-i".equals(args[i])) {
value = getParameterValue(args, ++i);
if (value != null) {
ret.setInputGCLogPath(value);
}
} else if ("-o".equals(args[i])) {
value = getParameterValue(args, ++i);
if (value != null) {
ret.setOutputPath(value);
}
} else if ("-st".equals(args[i])) {
value = getParameterValue(args, ++i);
if (value != null) {
SimpleDateFormat sdf = new SimpleDateFormat(
"yyyy/MM/dd HH:mm:ss");
try {
ret.setStartTime(sdf.parse(value));
} catch (ParseException e) {
System.out
.println("Warning: [-st starttime]'s format error. (expect 'yyyy/MM/dd HH:mm:ss')");
}
}
}
}
if (ret.getInputGCLogPath() == null || ret.getOutputPath() == null) {
ret = null;
}
return ret;
}
private String getParameterValue(String[] args, int i) {
String ret = null;
if (i < args.length) {
ret = args[i];
}
return ret;
}
public static void main(String[] args) {
GCLogToCSV gcLogToCSV = new GCLogToCSV(args);
gcLogToCSV.excute();
}
public void printUsage() {
System.out.println("Usage:");
System.out
.println("\tGCLogToCSV -i gclogpath [-o outputcsvpath] [-st starttime(yyyy/MM/dd HH:mm:ss)]");
}
private boolean getGCInfo(GCEvent event, GCInfo gcinfo, String type) {
boolean ret = false;
if (type == null || "".equals(type)) {
gcinfo.postUsed = event.getPostUsed();
gcinfo.total = event.getTotal();
gcinfo.pause = event.getPause();
return true;
}
for (Iterator i = event.details(); i.hasNext();) {
Object o = i.next();
if (o instanceof GCEvent) {
final GCEvent subEvent = (GCEvent)o;
if (subEvent.getType().toString().equals(type)) {
gcinfo.postUsed = subEvent.getPostUsed();
gcinfo.total = subEvent.getTotal();
gcinfo.pause = subEvent.getPause();
ret = true;
break;
}
}
}
return ret;
}
private class GCInfo {
public int postUsed;
public int total;
public double pause;
}
private class Env {
private Date startTime;
private String inputGCLogPath;
private String outputPath;
private String outputNewCSV;
private String outputOldPermCSV;
private String outputHeapCSV;
public Date getStartTime() {
return startTime;
}
public void setStartTime(Date startTime) {
this.startTime = startTime;
}
public String getInputGCLogPath() {
return inputGCLogPath;
}
public void setInputGCLogPath(String inputGCLogPath) {
this.inputGCLogPath = inputGCLogPath;
if (this.outputPath == null) {
setOutputPath(inputGCLogPath);
}
}
public String getOutputPath() {
return outputPath;
}
public void setOutputPath(String outputPath) {
this.outputPath = outputPath;
this.outputNewCSV = outputPath + "_new.csv";
this.outputOldPermCSV = outputPath + "_old_perm.csv";
this.outputHeapCSV = outputPath + "_heap.csv";
}
public String getOutputNewCSV() {
return outputNewCSV;
}
public String getOutputOldPermCSV() {
return outputOldPermCSV;
}
public String getOutputHeapCSV() {
return outputHeapCSV;
}
}
}
分享到:
相关推荐
当日志文件达到预设大小时,gclog会自动创建新的日志文件,同时保持文件命名规则的一致性,便于后期检索和分析。 3. **自动删除过期日志**: 日志管理中一个常见的问题是旧日志文件的堆积,占用大量存储空间。gc...
这将使JVM在`gc.log`文件中输出包括垃圾回收细节、时间戳等在内的信息,便于我们后续分析。 然后,我们引入了GCViewer工具,这是一个图形化的GC日志分析工具,由Chris Newland开发。GCViewer可以从GC日志中提取数据...
1. **性能优化**:通过分析GC日志,可以识别出频繁的垃圾收集事件,这可能是导致应用响应时间变慢或系统暂停时间过长的原因。 2. **内存泄漏检测**:如果GC日志显示内存使用持续增加,而无法被正常回收,可能存在...
本文将深入探讨“c# log日志类和日志分析器”的相关知识点,包括日志的创建、存储、分析以及提供的源码在实际项目中的应用。 首先,让我们了解什么是日志。日志是程序运行过程中产生的事件记录,这些记录包含了...
[GCViewer](https://github.com/chewiebug/GCViewer) 是一款开源的GC日志分析工具。项目的 GitHub 主页对各个指标提供了完整的描述信息 你需要安装了JDK或者Java. 解压之后, 然后双击点击 start.cmd 当然, 直接在...
`GChisto`是一款专门用于分析GC日志的离线工具,虽然其官网可能已经不可访问,但通过搜索引擎如百度,仍可以找到相关的资源和使用教程。 GChisto的主要功能在于帮助开发者和运维人员解析、可视化和理解GC日志,从而...
3. **内存配置调整**:分析GC日志可以帮助确定是否需要调整Java虚拟机的内存参数,如新生代大小、老年代大小等。 4. **垃圾收集器选择**:不同的GC算法有不同的性能特点,gchisto的分析结果可以为选择合适的垃圾...
例如,`-Xlog:gc:./gc.log`将GC日志输出到当前目录的`gc.log`文件。 3. **`decorators`** 部分允许你添加装饰器,以增强日志输出的信息,比如时间戳(`time`)、进程ID(`pid`)等。 4. **`output-options`** 允许...
GC的效率直接影响到程序的运行速度和内存使用,而分析GC日志是优化其性能的关键步骤。GCViewer 1.34便是一款专门用于解析和可视化Java GC日志的工具,它能够帮助开发者更直观地理解内存管理的情况,从而找出可能存在...
通过分析GC日志,可以了解Java虚拟机中的内存使用情况。从上面的输出结果可以看到,Java虚拟机中的堆内存被分为三个部分:Young Generation、Old Generation和Perm Generation。 Young Generation是用于存储短期...
JDK自带的JConsole、VisualVM和JFR(Java Flight Recorder)等工具可以帮助我们实时监控和分析GC行为。JFR尤其强大,能够提供丰富的事件和性能指标,对GC调优非常有帮助。 总结,学习和理解GC参数,尤其是G1垃圾...
此外,可以使用`-Xloggc:gc.log`指定日志输出文件,然后通过工具如GCViewer进行日志分析,以获取更直观的GC行为可视化。 2. 在生产环境下,由于直接修改JVM参数可能影响线上服务,因此通常推荐使用专门的监控工具。...
4. **暂停时间分布**:分析GC暂停时间的分布,帮助定位导致应用暂停时间过长的问题。 5. **GC趋势**:通过图表展示GC行为随时间的变化,便于观察内存使用和GC活动的规律。 对于Old Generation问题,GChisto可以帮助...
在使用GCViewer时,首先要确保JVM开启了相应的日志记录,这通常通过设置JVM参数来实现,例如使用`-XX:+PrintGCDetails`和`-Xloggc:gc.log`来开启标准GC日志。然后,将生成的日志文件导入GCViewer,工具会自动解析并...
### Tomcat GC 优化配置详解 #### 一、概述 在服务器端应用中,Java虚拟机(JVM)的性能优化至关重要,特别是对于像...此外,定期分析GC日志可以帮助我们更好地理解系统的运行状态,并据此做出进一步的优化决策。
- **GC日志分析**:通过设置合理的JVM参数来收集GC日志,并使用工具如GC Log Analyzer、VisualVM等分析GC行为,优化垃圾回收策略。 - **代码优化**:根据性能分析的结果,针对性地优化代码逻辑,减少不必要的对象...
为了分析具体的问题,我们需要查看`hs_err_pid32506.log`日志文件。这个文件通常记录了JVM崩溃时的详细信息,包括堆栈跟踪、系统环境变量、JVM参数等,这些信息对于诊断问题至关重要。我们可以通过以下步骤进行分析...