记录帖:碰到的一些Java问题

标签: Java jvm btrace Java Cases Java Troubleshooting | 发表时间:2011-08-09 22:48 | 作者:bluedavy gengmao
出处:http://blog.bluedavy.com

这个贴用于记录自己碰到过的一些Java问题,会根据经验不断增加,以便总结,:)

Case: 某应用出现启动后集群中部分node成功,部分node失败
解决过程:
1、失败的node抛出的是NoClassDefFoundError,这些node在环境上和应用包上是完全一致的,因此猜想是classloader装载class时出现了什么问题;
2、在启动参数上增加了-XX:+TraceClassLoading,想看看成功的node和失败的node是不是从第一个地方加载的相应的类,悲催的是成功的node加上了这参数后启动超慢,于是只好放弃;
3、由于不能用TraceClassLoading,只好从ClassLoader方面来跟踪这个类的加载,于是从应用层上做了相应的分析,找出了相应的classloader,然后用btrace相应的进行了跟踪,才终于发现成功的node和失败的node装载此类时不是从同一地方装载的,而其中有一个地方的这个类引用了一个不存在的类,于是就出现了NoClassDefFoundError。
总结:
在经过分析后,猜想是在这两个不同的node上classloader在list一个目录下的文件时,出现了顺序不同的现象,于是后来写了一个简单的程序在两个node上list那个目录的文件,发现返回的顺序果然不同,这个具体的原因为File.listFiles最后会调用到readdir函数,而这个函数返回的文件列表是按inode number排序的,因此在每台linux机器上确实有可能不同,当一个目录下有两个jar中有相同名字但不同内容的class时(话说这也是java应用中比较麻烦的问题,这个专门写篇blog来说下,java 8的模块化真的非常重要),就悲催了,一个保护做法是在实现classloader时,最好是先对listFiles排下序,避免集群中node出现表现不一致的问题。

Case: 某应用GC频繁但不一直不抛OOM的问题
解决过程:
这个应用是期待在内存不够的情况下快速抛出OOM的,但在执行中却发现执行了4个多小时的Full GC,就是没有抛OOM,导致应用出现了问题,从GC代码来看,目前要比较快的触发OOM,只能是调整GCTimeLimit和GCHeapFreeLimit,不过都不好调,后来暂时是靠调整了GCHeapFreeLimit来帮助快速抛出OOM。

Case: 某应用堆外内存泄露的bug
具体解决过程可参考这篇blog:http://blog.bluedavy.com/?p=205这篇blog
总结:
堆外内存泄露基本就是靠google perf-tools来查找了,目前来看堆外内存泄露基本都是使用Deflater,却没有显式调用end造成的。

Case: 某应用压测时压力上不去的问题
解决过程:
1、查看压测的目标服务器的cpu、网卡流量,发现都没到瓶颈;
2、继续查看压测的目标Server的线程状况,发现Server的线程数也没到瓶颈,有个诡异的现象是随着客户端施加的压力上升,服务器端线程数也没上升,而且网卡流量也没上升;
3、于是猜测是客户端本身的问题,客户端的CPU、网卡流量也没到瓶颈,但发现客户端的线程数随着施加的请求数增加,也没上升,因此猜想是客户端这个地方的线程数已经达到了最大值;
4、由于代码是第三方的,于是用btrace写了个脚本,跟踪查找了该线程池的最大线程数,发现果然是这个最大线程数比较小,因此做了相应的修改,放大最大线程数,继续压测就OK了。
ps: 这个Case还出现了一个状况,就是客户端的网卡流量随着施加的压力上升,却没发生变化,因此猜测是网络上有流量限制…
总结:
从查这次的问题来看,在压测时压力上不去时,需要查看从请求发起到响应返回的整个过程,资源的消耗状况,是否某个地方资源消耗到极限了,如果硬件资源未到极限,通常会是线程blocked或线程被消耗完了。

Case: 某应用GC频繁的问题
这个专门写了一篇blog来描述,具体请见:http://blog.bluedavy.com/?p=290

Case: 某应用一直没响应。
解决过程:
1、jstack多次后分析,很多的线程都在Blocked状态,等待一把锁,而持有这把锁的线程一直停在了Log4j的ConsoleLog的write上;
2、于是问题就集中到为什么ConsoleLog write的时候竟然会停住,最早猜测的原因是console是不是也输出到了一个文件,而这个文件出问题了,但经过检查发现一切正常;
3、通过ps auxf查看脚本看看console有没有输出到文件,发现这个脚本嵌套了好几层,但都输出到了外部的文件,而外部这个文件是没什么问题的;
4、仔细查看发现这个Java进程是在代码里通过调用脚本启动的,猜想是不是没有正确处理标准输出流和错误流造成的,于是翻看代码,发现代码只处理了输出流,但没处理错误流,并且在处理输出流时只处理了10000行,超过10000的时候就没再去读了,对于这种未将console重定向到外部文件的场景,linux会将其写到一个缓冲区,缓冲区写满后就会导致应用程序阻塞住,这个在Java的API上也有说明:
The parent process uses these streams(Process.getOutputStream(), Process.getInputStream(), Process.getErrorStream()) to feed input to and get output from the subprocess. Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, and even deadlock.
5、到这步后就可以确认问题的原因了。
解决方法:
1、把输出到Console的Logger方式去掉了,这样自然就没问题了;
2、程序上修改,不是读到1w行就不读了,而是一直读到没有输出流和错误流了才结束,通常来说比较正确的做法请见这篇贴:http://goo.gl/sllmv
总结:
在Java中启动外部程序时一定要注意正确处理输出流和错误流。

相关 [记录 java 问题] 推荐:

记录帖:碰到的一些Java问题

- gengmao - BlueDavy之技术blog
这个贴用于记录自己碰到过的一些Java问题,会根据经验不断增加,以便总结,:). Case: 某应用出现启动后集群中部分node成功,部分node失败. 1、失败的node抛出的是NoClassDefFoundError,这些node在环境上和应用包上是完全一致的,因此猜想是classloader装载class时出现了什么问题;.

Java写xml文件的编码问题

- - CSDN博客推荐文章
最近项目中需要生成xml格式的配置文件,用的是 javax.xml.transform.Transformer 类中提供的transform方法,在本地执行没问题,但是一旦把工程部署到Tomcat下运行,就会出现中文乱码的现象,纠结了许久,在大神的帮助下终于解决了. 有篇文章其实已经讲的很清楚了,链接如下:.

Java String 的十大常见问题

- - ITeye博客
Java字符串经常被问到的排名前十的问题.    1、如何比较字符串. 使用 “==”  还是 “equals()”.   简单来讲,“==”比较的是引用(对象的内存地址),“equals()” 比较值是否相等. 除非你想检测两个字符串是否是同一对象,否则都用equals().   当然了解字符串池的概念更好.

java socket 长连接read阻塞问题

- - PHP & Java
1 约定发送的数据长度,比如 http的 keepAlive 就是必须依赖这个的 Content-Length. 2 设置超时的时间,根据我的经验,只有在Socket级别设置才有效. socket.setSoTimeout(100); // 如果超过100毫秒还没有数据,则抛出 SocketTimeoutException.

15个易遗忘的Java问题

- - ITeye博客
1.Java中的基本数据类型以及所占内存大小. short    2字节. float    4字节. double    8字节. char    2字节(Unicode-16).     布尔类型boolean比较特殊,尽管Java虚拟机定义了boolean类型,但虚拟机对boolean类型的支持是有限的,没有为boolean值单独设计JVM指令.

Java静态代码块的问题

- - ITeye博客
在查看别人代码的时候 看到了 static静态代码块  之后经过搜索和自己的亲试,下面贴出测试代码和解释. System.out.println("父类--静态代码块");. System.out.println("父类--构造方法");. System.out.println("父类--非静态代码块");.

Java最小堆解决TopK问题

- - ITeye博客
其实我们与大数据并不遥远,比如要从海量数据中按大小或频率挑出top k,假定机器是多核的内存有限的,我们采用多线程分块处理数据,最后合并处理. 那么,处理每一块数据的top k(i)可以采用哪些算法呢. TopK问题是指从大量数据(源数据)中获取最大(或最小)的K个数据. TopK问题是个很常见的问题:例如学校要从全校学生中找到成绩最高的500名学生,再例如某搜索引擎要统计每天的100条搜索次数最多的关键词.

记录碰到的HBase问题

- Adam - BlueDavy之技术blog
目前NoSQL产品最被人诟病的就是其稳定性,不得不承认,目前HBase离做到数据库那样的高稳定还有距离(丢数据、不能读写、DDL失败等严重问题),这篇blog将用来记录我们在运维HBase时碰到的问题(会不断更新),希望能给使用HBase的同学有一些帮助. 1、单台regionserver的region数很多后写速度疯狂下降.

使用AOP与注解记录Java日志

- - ImportNew
有些时候,我想要把每个运行过的方法接收到的参数、返回值和执行时间等信息记录(通过slf4j 和 log4j)下来. 在AspectJ、jcabi-aspects和Java注解的帮助下我实现了这个想法. 在log4j中可以看到以下输出:. 接下来我们来看看它是如何工作的. 注解是Java 6中采用的一种技术( 译注:其实Java 5就有注解了).

Java通过mysql-connector-java-8.0.11连接MySQL Server 8.0遇到的几个问题

- - 编程语言 - ITeye博客
这次新安装了一个MySQL数据库,然后navicat连接数据库一点问题没有. 但是通过Java的jdbc连接却怎么都建立不了连接. 网上找了很久找到了原因:. 数据库用的是Mysql8版本,但工程里面mysql驱动包却是5.1.37版本. 只需修改驱动包为8.0.11版本即可. 而且驱动的包也改变了,由原来的:/generatorSqlmapCustom/lib/mysql-connector-java-5.1.28-bin.jar.