行是靠Java Platform Debugger Architecture(JPDA)来进行的。 所有真正的执行还是要依赖目标JVM的,所以当目标JVM堆内存不足,且长时间GC占用CPU时间片时,Attach是很难执行的。
要想获取更相信的信息,请参考:
结构化日志方式
- 脚本语言:Python、Node.js
- sed命令
- awk命令
- grep命令
参考脚本
with open('E:/logAnalysis/out.txt', 'w', encoding='UTF-8') as fo:
with open('E:/logAnalysis/request.log',encoding='UTF-8') as f:
for line in f:
if line[0:8] != '20180110':
continue
time = line[12:21]
line = line[22:].lstrip()
thread = line[0:line.find(" ")]
line = line[len(thread) + 1:].lstrip()
level = line[0:line.find(" ")]
line = line[len(level) + 1:].lstrip()
clazz = line[0:line.find(" ")]
line = line[len(clazz) + 1:].lstrip()
n1 = line[0:line.find(" ")]
line = line[len(n1) + 1:].lstrip()
n2 = line[0:line.find(" ")]
line = line[len(n2) + 1:].lstrip()
content = line[2:].strip()
request = 0 if content.find('[http]preHandle') >= 0 else 1
fo.write("" + time + "^" + thread + "^" + level + "^" + clazz + "^" + n1 + "^" + n2 + "^" + str(request) + "\n")
- DateFormat线程不安全的原因
说严禁点,其实是SimpleDateFormat的parse和format方法线程不安全。究其原因是因为其中使用了一个共享的calendar变量来进行日期与实时间的处理。在format时,先进行了一个calendar的setTime操作。这里就导致了多线程环境下,结果的不一致。
// Called from Format after creating a FieldDelegate
private StringBuffer format(Date date, StringBuffer toAppendTo,
FieldDelegate delegate) {
// Convert input date to time field list
calendar.setTime(date);
- 上面虽然引起了堆内存大量占用,但是并没有OOM,思考原因
上面说了堆内存被大量占用,且有个死循环一直分配内存。奇怪的是却一直没有报出OutOfMemmoryError。这里需要去了解一下抛出OutOfMemmoryError的时机,参考JVM源码分析之临门一脚的OutOfMemoryError完全解读。
个人猜测是因为,尝试分配内存时,发现内存不足,尝试进行GC,一次GC时间达到了半分钟。GC后,由于有其他线程可以释放一部分内存,又可以让死循环多分配点内存,最终持续进行分配与GC,始终达不到触发OOM错误的时机,故没有抛出OOM。
PS
第一次尝试这种写作风格,欢迎各位提出意见与建议。如果觉得文章不错,欢迎关注和点赞哈,您的支持是我最大的动力。本地还有一些存货,有机会的话我会继续写这个系列,希望大家支持~