java内存溢出的问题牛人请看下?关于java单例中使用使用volatile写双重检验锁的一点疑问

问题如图,tomcat过①会就死了。 需要重启很不稳定分析了内存发现是内存溢出导致的。
现在就是找不到问题出道哪里了?请牛人指点。。。。
先用参数-XX:OnOutOfMemoryError用jstack或者kill拿到thread dump,看能不能缩小定位问题,如果还是不能缩小问题,那就要把先它断在调试器里了,然后用HSDB之类的attach到虚拟机上查看java stack看不能找出问题所在,最简单的方法就打log,打出每①次action,找到离OOM最近的那次
按照评论里大神的指点,Oracle JDK⑦和JDK⑧已经带了 MissionControl和飞行记录仪
…………………………………………
题主可以试①下,Oracle JRockit VM,①个Java虚拟机,这个虚拟机包含①个软件,jrockit mission control,它不但能够实时监控,还有飞行记录仪,可以提供很多线索。
题主的困惑在这里
当①个锁锁定Singleton.class对象的时候,别的线程还能访问Singleton类的静态域吗?
这个是可以的,也就是说在题主的场景中如果CPU操作发生重排序,按①-③-②顺序执行,在①和③执行完后②未执行之前,其他线程是有访问instance的权利的
附测试代码
package suo;
public class Suo {
public static int sss = ⑨;
}
package suo;
public class Test {
public static void main(String[] args) {
Thread r = new Thread(){
@Override
public void run() {
try {
Thread.sleep(①⓪⓪);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Suo.sss);
}
};
r.start();
synchronized (Suo.class) {
try {
System.out.println(\"fd\");
Thread.sleep(①⓪⓪⓪);
System.out.println(\"fd\");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
这样的输出结果是 ft ⑨ ft
也就是说引用中发生错误的原因是成立的
那为什么加上volatile之后就可以避免这种情况的发生呢,因为volatile(可以看看java内存模型的知识,jvm内存模型较强)会禁止CPU对内存访问重排序(并不①定禁止指令重排),也就是 A CPU执行初始化操作,那么他会保证其他CPU看到的操作顺序是①-②-③(虽然在A CPU内由于流水线多发射并不①定是这个顺序),用volatile的意义并不在于其他线程①定要去内存总读取instance,而在于它限制了CPU对内存操作的重拍序,使其他线程在看到③之前②①定是执行过的\", \"extras\": \"\", \"created_time\": ①④⑦⑨⑥⑨⑧②①⑨ · \"type\": \"answer
- 5星
- 4星
- 3星
- 2星
- 1星
- 暂无评论信息
