Java常见问题分析(内存溢出、内存泄露、线程阻塞等)

时间:2022-09-03 21:08:30
  1. Java垃圾回收机制(GC)

    1.1 GC机制作用

    1.2 堆内存3代分布(年轻代、老年代、持久代)

    1.3 GC分类

    1.4 GC过程
  2. Java应用内存问题分析

    2.1 Java内存划分

    2.2 Java常见内存问题

    2.3 ML(内存泄露) OOM(内存溢出)问题现象及分析

    2.4 IBM DUMP分析工具使用介绍
  3. Java应用CPU、线程问题分析

Java垃圾回收机制(GC)

1.GC机制作用

1.1 JVM自动检测和释放不再使用的对象内存

1.2 Java 运行时JVM会执行 GC,不再需要显式释放对象

例:Object.finallize()、 Windows.dispose()、 System.gc()

Java常见问题分析(内存溢出、内存泄露、线程阻塞等)

2.Java堆3代分布

Java常见问题分析(内存溢出、内存泄露、线程阻塞等)

关于Java堆3代分布情况,可通过命令:jmap –heap pid 查看

Java常见问题分析(内存溢出、内存泄露、线程阻塞等)

3.GC分类

3.1 Young GC(Minor GC):收集生命周期短的区域(Young)

(1) 清空Eden+from survivor中所有no ref的对象占用的内存

(2) 将Eden+from survivor中所有存活的对象copy到to survivor中

(3) 一些对象将晋升到old中: to survivor放不下的或存活次数超过turning threshold中的

3.2 Full GC(Major GC):收集生命周期短的区域(Young)和生命周期比较长的区域(Old),对整个堆进行垃圾收集,有时也会回收持久区(Perm)

(1) 清空heap中no ref的对象

(2) 清空permgen中已经被卸载的class信息

4.GC过程

(1) 新生成的对象在Eden区完成内存分配

(2) 当Eden区满,再创建对象,会因为申请不到空间触发YGC,进行young(eden+1survivor)区的垃圾回收(为什么是eden+1survivor:两个survivor中始终有一个survivor是空的,空的那个被标记成To Survivor)

(3) YGC时,Eden不能被回收的对象被放入到空的survivor(也就是放到To Survivor,此时Eden被清空),另一个survivor(From Survivor)里不能被GC回收的对象也会被放入To Survivor,始终保证一个survivor是空的(YGC完成之后,To Survivor 和 From Survivor的标记互换)

(4) YGC结束后,若存放对象的survivor满,则这些对象被copy到old区,或者survivor区没有满,但是有些对象已经足够Old(超过XX:MaxTenuringThreshold),也被放入Old区

(5) 当Old区被放满的之后,进行完整的垃圾回收,即 FGC

(6) FGC后,若Survivor及old区仍然无法存放从Eden复制过来的部分对象,导致JVM无法在Eden区为新对象创建内存区域,则出现OOM错误

Java常见问题分析(内存溢出、内存泄露、线程阻塞等)

Java应用内存问题分析方法

1.Java内存划分

可粗略划分三类:

1.1 堆内存

存放由 new 创建的对象和数组,在堆中分配的内存,由 Java 虚拟机的自动垃圾回收器来管理

Java常见问题分析(内存溢出、内存泄露、线程阻塞等)

1.2 栈内存

在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配(更准确地说是保存了引用的堆内存空间的地址,java中的“指针”)

1.3 永久保存区、方法区(Permanent Generation)

用于存储已被虚拟机加载的类信息、常量、静态变量等

Java常见问题分析(内存溢出、内存泄露、线程阻塞等)

2.Java常见的内存问题表现形式:

2.1 OutOfMemory:内存溢出

2.2 Memory Leak:内存泄露

二者共同点:

(1) 通常最终的状态就会导致OOM错误

(2) 在Java堆或本地内存中都可能发生

二者不同点:

(1) ML是已经分配好的内存或对象,当不再需要,没有得到释放 而OOM则是没有足够的空间来供jvm分配新的内存块

(2) ML的内存曲线总体上是一条斜向上的曲线而OOM不是,反之未必

3.内存溢出类型:

虚拟机栈溢出、本地方法栈溢出、方法区溢出、堆溢出、运行时常量池溢出

异常类型:

(1) java.lang.OutOfMemoryError: Java heap space

堆内存溢出

优化:通过-Xmn(最小值)–Xms(初始值) -Xmx(最大值)参数手动设置 Heap(堆)的大小。

(2) java.lang.OutOfMemoryError: PermGen space

PermGen Space溢出(方法区溢出、运行时常量池溢出)

优化:通过MaxPermSize参数设置PermGen space大小。

(3) java.lang.*Error

栈溢出(虚拟机栈溢出、本地方法栈溢出)

优化:通过Xss参数调整

Demo代码 :

// Java 堆溢出
public static void main(String[] args) {
List<OOMObject> list = new ArrayList<JavaHeapSpace.OOMObject>();
while (true) {
list.add(new OOMObject());
}
} static class OOMObject { }
  // 虚拟机栈溢出
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(add());
} public static int add(){
return add();
}
// 方法区溢出
public static void main(String[] args) {
while (true) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(OOMObject.class);
enhancer.setUseCache(false);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method,
Object[] args, MethodProxy proxy) throws Throwable {
return proxy.invoke(obj, args);
}
});
enhancer.create();
}
} static class OOMObject { }
// 运行时常量池溢出
public static void main(String[] args){
// TODO Auto-generated method stub
List<String> list = new ArrayList<String>();
int i = 0;
while (true ){
list.add(String. valueOf(i++).intern());
}
}
// 内存泄露模拟
public static void main(String[] args) {
// TODO Auto-generated method stub
List<int[]> list = new ArrayList<int[]>(); Runtime run = Runtime.getRuntime(); int i=1; while(true){
int[] arr = new int[1024];
list.add(arr); if(i++ % 1000 == 0 ){
System.out.print("最大堆内存=" + run.maxMemory() / 1024 / 1024 + "M, ");
System.out.print("已分配内存=" + run.totalMemory() /1024 / 1024 + "M, ");
System.out.print("剩余空间内存=" + run.freeMemory() / 1024 / 1024 + "M, ");
System.out.println("最大可用内存=" + ( run.maxMemory() - run.totalMemory() + run.freeMemory() ) / 1024 / 1024 + "M");
sleep(1000);
}
}
} public static void sleep(long time) {
try {
Thread.sleep(time);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

4.内存泄露现象

Java常见问题分析(内存溢出、内存泄露、线程阻塞等)

heapspace:OutOfMemoryError

Java常见问题分析(内存溢出、内存泄露、线程阻塞等)

开发人员的分析、解决思路

内存对象申请未释放(未及时释放)

线程问题

分别从堆dump和线程dump进行分析:

jmap -dump:format=b,file=heap.dump pid

jstack pid >> thread.dump

5.JAVA DUMP分析工具

IBM HeapAnalyzer:ha456.jar

IBM Thread and Monitor Dump Analyzer:jca457.jar

堆dump分析

占用内存较多代码块

分析代码快上下文

分析占用内存的对象内容

Java常见问题分析(内存溢出、内存泄露、线程阻塞等)

线程dump分析

活跃线程

阻塞线程

等待资源线程

Java常见问题分析(内存溢出、内存泄露、线程阻塞等)

Java应用CPU问题分析方法

1.程序响应慢,CPU高

(1) ThreadDump

jstack pid >> thread.dump

(2) 找到导致cpu高的线程 top -H -p pid

(3) pid 十进制转十六进制

http://tool.oschina.net/hexconvert/

(4) 找到对应的线程UE打开 threaddump文件查找:按十六进制关键字找到对应的线程,把相关的方法找出来,可以精确到代码的行号

2.程序响应慢,CPU不高

一般表现为thread struck在了i/o、db等

实例:

IO阻塞(程序表现为响应慢)

线程状态为“in Object.wait()”,说明正在等待线程池可用资源,由于线程池满导致新的IO请求处于排队等待状态,且发生在:at com.iflytek.diange.data.provider.sendsong.impl.SendSongImpl.getSendSongInfosByUserId(SendSongImpl.java:92)行

Java常见问题分析(内存溢出、内存泄露、线程阻塞等)

3.程序无响应

死锁(程序表现为无响应)

线程状态为“waiting to lock”: 两个线程各持有一个锁,又在等待另一个锁,故造成死锁,且发生在DeadLockTest.java:39行

Java常见问题分析(内存溢出、内存泄露、线程阻塞等)

Java常见问题分析(内存溢出、内存泄露、线程阻塞等)的更多相关文章

  1. 内存溢出&comma;内存泄漏&comma;CPU溢出区别

    内存溢出 out of memory,就是你要的内存空间超过了系统实际分配给你的空间,此时系统相当于没法满足你的需求,就会报内存溢出的错误 内存泄漏是指你向系统申请分配内存进行使用(new),可是使用 ...

  2. JS高阶---闭包缺点(内存溢出与泄露)

    [大纲] [主体] (1)闭包优缺点 .延长局部变量的生命周期2.外部访问函数内部变量 闭包的优点同时也是它的缺点,就是 (2)解决方案 .能不用闭包就不用(很难做到,因为应用较多) .及时释放--- ...

  3. 【性能诊断】七、并发场景的性能分析(windbg案例,线程阻塞)

    简单整理一个测试Demo,抓取dump并验证,步骤如下: Symbol File Path:SRV*C:\Symbols*http://msdl.microsoft.com/download/symb ...

  4. 详解Java多线程编程中LockSupport类的线程阻塞用法

    LockSupport类是Java6(JSR166-JUC)引入的一个类,提供了基本的线程同步原语.LockSupport实际上是调用了Unsafe类里的函数,归结到Unsafe里,只有两个函数: p ...

  5. Java常见内存溢出异常分析&lpar;OutOfMemoryError&rpar;

    原文转载自:http://my.oschina.net/sunchp/blog/369412 1.背景知识 1).JVM体系结构 2).JVM运行时数据区 JVM内存结构的相关可以参考: http:/ ...

  6. java命令分析线程死锁以及内存泄漏

    一.介绍 jstack是java虚拟机自带的一种堆栈跟踪工具.jstack用于打印出给定的java进程ID或core file或远程调试服务的Java堆栈信息,如果是在64位机器上,需要指定选项&qu ...

  7. Java虚拟机6:内存溢出和内存泄露、并行和并发、Minor GC和Full GC、Client模式和Server模式的区别

    前言 之前的文章尤其是讲解GC的时候提到了很多的概念,比如内存溢出和内存泄露.并行与并发.Client模式和Server模式.Minor GC和Full GC,本文详细讲解下这些概念的区别. 内存溢出 ...

  8. Java中内存溢出与内存泄露

    内存溢出 内存溢出(out of memory),是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory:比如申请了一个integer,但给他存了long才能存下的数,就会发 ...

  9. 什么是内存溢出以及java中内存泄漏5种情况的总结

    内存泄漏定义(memory leak):一个不再被程序使用的对象或变量还在内存中占有存储空间. 一次内存泄漏似乎不会有大的影响,但内存泄漏堆积后的后果就是内存溢出.内存溢出 out of memory ...

随机推荐

  1. OOM异常产生的原因和处理方法

    一般而言,android中常见的原因主要有以下几个: 1.数据库的cursor没有关闭. 2.构造adapter没有使用缓存contentview. 3.调用registerReceiver()后未调 ...

  2. BZOJ3067 &colon; Hyperdrome

    设f[i][j]表示前i个字母中字母j出现的次数对2取模的结果. 若[l,r]经过重组可以形成回文串,则需满足f[l-1][j]与f[r][j]至多有1位不同. 将f[i]用一个long long表示 ...

  3. CAD字体显示错乱问题解决方案

    最近这两天一直在画竣工图,用CAD用得挺多的,所以老是发现一些问题.今天在打开别人发过来的图纸时,我看到竟然还有钢筋符号无法显示…… 像这种问题的解决,据我所知就两种方法: 一.替换使用的字体 首先选 ...

  4. windows下查看某个端口被哪个程序占用的方法

    经常,我们在启动应用的时候发现系统需要的端口被别的程序占用,如何知道谁占有了我们需要的端口,很多人都比较头疼,下面就介绍一种非常简单的方法,希望对大家有用 假如我们需要确定谁占用了我们的9050端口 ...

  5. SpringBoot中Application开启与关闭

    0.声明 缘由:没有学过或者没有经历SpringBoot的Application运行机制的话,一定会好奇,博主为啥会写一篇关闭开启的博文,是不是好幼稚?(/o(╥﹏╥)o),待我娓娓道来......为 ...

  6. 关于ComboBox的控件事件CBN&lowbar;SELCHANGE总是取到旧值的问题

    我发现复选框,选择以后,在这个事件函数中,总是取到旧值,读了这个朋友的文章,找到了解决方法. 下面是参考的文章: http://scorpiomiracle.iteye.com/blog/710511 ...

  7. 使用google的pprof工具以及在gin中集成pprof

    首先我们得先安装这两个工具: google的pprof工具链 go get -u github.com/google/pprof gin的pprof工具 go get github.com/DeanT ...

  8. 2019年3月8日A股百点暴跌行情思考

    本人操作: [海通证券]:早盘挂单并撤单,盘中高位卖出,尾盘低位接回. 总结 - 正确:持股数量不变,成本降低. [信雅达]:早盘低开加仓,盘中高位卖出,跌后接回,尾盘跌停. 总结 -  正确:加仓, ...

  9. CentOS 7&period;4安装Nginx 1&period;14&period;0

    一.安装所需环境   1.gcc 安装         yum install gcc-c++    

  10. SpringMVC探究-----常用获取传递参数的方法

       1.@RequestParam @RequestParam 常用来映射请求参数,它有三个属性可以配置: value 值即请求参数的参数名 required 该参数是否必须. 默认为 true d ...