精华内容
下载资源
问答
  • 什么是OOM?如何解决OOM问题!

    万次阅读 多人点赞 2018-07-12 21:22:54
    1、什么是OOM? 2、为什么会有OOM? 3、为什么Android会有APP的内存限制 4、有GC自动回收资源,为什么还会有OOM? 5、怎么来避免OOM产生呢? 1、什么是OOM?  程序申请内存过大,虚拟机无法满足我们,然后...


    1、什么是OOM?

      程序申请内存过大,虚拟机无法满足我们,然后自杀了。这个现象通常出现在大图片的APP开发,或者需要用到很多图片的时候。通俗来讲就是我们的APP需要申请一块内存来存放图片的时候,系统认为我们的程序需要的内存过大,及时系统有充分的内存,比如1G,但是系统也不会分配给我们的APP,故而抛出OOM异常,程序没有捕捉异常,故而弹窗崩溃了

    2、为什么会有OOM?

      因为Android系统的APP每个进程或者虚拟机有最大内存限制,一旦超过这个限制系统就会抛出OOM错误。跟手机剩余内存是否充足没有多少关系。

    3、为什么Android会有APP的内存限制

      (1) 要开发者使用内存更加合理。限制每个应用可用内存上限,避免恶意程序或单个程序使用过多内存导致其他程序的不可运行。有了限制,开发者就必须合理使用资源,优化资源使用

      (2) 屏幕显示内容有限,内存足够即可。即使有万千图片千万数据需要使用到,但在特定时刻需要展示给用户看的总是有限的,因为屏幕显示就那么大,上面可以放的信息就是很有限的。大部分信息都是处于准备显示状态,所以没必要给予太多heap内存。必须一个ListView显示图片,打个比方这个ListView含有500个item,但是屏幕显示最多有10调item显示,其余数据是处于准备显示状态。

      (3) Android多个虚拟机Davlik的限制需要。android设备上的APP运行,每打开一个应用就会打开至少一个独立虚拟机。这样可以避免系统崩溃,但代价是浪费更多内存。

    4、有GC自动回收资源,为什么还会有OOM?

      Android的GC会按照特定的算法来回收不使用的资源,但是gc一般回收的是无主的对象内存或者软引用资源。

      使用软引用的图片资源在一定程度上可以避免OOM。

      ps:不用的对象设置为null,是一个好习惯。不过更好的方法是,不用的图片直接recycle。因为有时候通过设置null让gc来回收还是来不及。

    5、怎么来避免OOM产生呢?

      简单通过SoftReference引用方式管理图片资源

      建一个SoftReference的hashmap,使用图片时,先检查这个hashmap是否有softreference,softreference的图片是否为空,如果为空将图片加载到softreference并加入haspmap。

    代码如下:

    import java.io.InputStream;
    import java.lang.ref.SoftReference;
    import java.net.HttpURLConnection;
    import java.net.URL;
    import java.net.URLConnection;
    import java.util.HashMap;
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.os.Handler;
    import android.os.Handler.Callback;
    import android.os.Message;
    import android.widget.ImageView;
    
    
    /**
     * 功能说明:异步加载图片
     *
     */
    
    public class AsyncImageLoaderCore {
        public Context context; // 做本地缓存时会用到
        public HashMap<String, SoftReference<Bitmap>> imageCache;// 软引用集合
    
        public AsyncImageLoaderCore(Context context) {
            this.context = context;
            this.imageCache = new HashMap<String, SoftReference<Bitmap>>();
        }
    
    
        public Bitmap loadBitmap(final String imageUrl, final ImageView imageView, final ImageCallback imageCallback) {
            if (imageCache.containsKey(imageUrl)) {
                SoftReference<Bitmap> softReference = imageCache.get(imageUrl);
                if (softReference.get() != null)
                    return softReference.get();
            }
    
            final Handler handler = new Handler(new Callback() {
                @Override
                public boolean handleMessage(Message msg) {
                    imageCallback.imageLoaded((Bitmap) msg.obj, imageView, imageUrl);
                    return false;
                }
            });
    
            new Thread() {
                @Override
                public void run() {
                    Bitmap bitmap = null;
                    try {
                        bitmap = getHttpBitmap(imageUrl);
                    } catch (Exception e) {
                        e.printStackTrace();
                        return;
                    }
    
                    if (null != bitmap) {
                        imageCache.put(imageUrl, new SoftReference<Bitmap>(bitmap));
                        handler.sendMessage(handler.obtainMessage(0, bitmap));
                    }
                }
            }.start();
            return null;
        }
        private final int MAX_PIC_LENGTH = 200000;// 最大字节长度限制[可调,最好不要超过200000]
        private final int SAMPLE_SIZE = 14;// 裁剪图片比列(1/14)[可调]
        /**
         * 获取网络图片
         */
        private Bitmap getHttpBitmap(String imgUrl) throws Exception {
            URL htmlUrl = new URL(imgUrl);
            URLConnection connection = htmlUrl.openConnection();
            HttpURLConnection conn = (HttpURLConnection) connection;
            if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
                InputStream inputStream = conn.getInputStream();
                byte[] bytes = changeToBytes(inputStream);
                if (bytes.length < MAX_PIC_LENGTH) {
                    return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
                } else if (bytes.length < MAX_PIC_LENGTH * SAMPLE_SIZE) {
                    BitmapFactory.Options options = new BitmapFactory.Options();
                    options.inJustDecodeBounds = false;
                    options.inSampleSize = SAMPLE_SIZE;
                    return BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
                }
            }
            return null;
        }
    
    
        /**
         * 将流转换成字节数组
         */
    
        public byte[] changeToBytes(InputStream inputStream) throws Exception
        {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];// 每次读取的字节长度
            int len = 0;
            while ((len = inputStream.read(buffer)) != -1)
            {
                outputStream.write(buffer, 0, len);
            }
            inputStream.close();
            return outputStream.toByteArray();
        }
        /**
         * 异步加载资源回调接口
         */
        public interface ImageCallback {
            public void imageLoaded(Bitmap bitmap, ImageView imageView, String imageUrl);
        }
    }
    展开全文
  • 什么是java OOM?如何分析及解决oom问题

    什么是java OOM?如何分析及解决oom问题?

    参考文章:

    (1)什么是java OOM?如何分析及解决oom问题?

    (2)https://www.cnblogs.com/ThinkVenus/p/6805495.html


    备忘一下。


    展开全文
  • OOM问题快速定位

    2020-01-13 14:04:50
    有一个Java服务出现了OOM(Out Of Memory)问题,定位了好久不得其法,请问有什么好的思路么? OOM问题,印象中之前写过,这里再总结一些相对通用的方案,希望能帮助到Java技术栈的同学。 某Java服务(假设PID=...

    有一个Java服务出现了OOM(Out Of Memory)问题,定位了好久不得其法,请问有什么好的思路么?

    OOM的问题,印象中之前写过,这里再总结一些相对通用的方案,希望能帮助到Java技术栈的同学。

    某Java服务(假设PID=10765)出现了OOM,最常见的原因为:

        有可能是内存分配确实过小,而正常业务使用了大量内存

        某一个对象被频繁申请,却没有释放,内存不断泄漏,导致内存耗尽

        某一个资源被频繁申请,系统资源耗尽,例如:不断创建线程,不断发起网络连接

    画外音:无非“本身资源不够”“申请资源太多”“资源耗尽”几个原因。

     

    更具体的,可以使用以下工具逐一排查。

    一、确认是不是内存本身就分配过小

    方法:jmap -heap 10765

    如上图,可以查看新生代,老生代堆内存的分配大小以及使用情况,看是否本身分配过小。

     

    二、找到最耗内存的对象

    方法:jmap -histo:live 10765 | more

    如上图,输入命令后,会以表格的形式显示存活对象的信息,并按照所占内存大小排序:

        实例数

        所占内存大小

        类名

    是不是很直观?对于实例数较多,占用内存大小较多的实例/类,相关的代码就要针对性review了。

     

    上图中占内存最多的对象是RingBufferLogEvent,共占用内存18M,属于正常使用范围。

    如果发现某类对象占用内存很大(例如几个G),很可能是类对象创建太多,且一直未释放。例如:

        申请完资源后,未调用close()或dispose()释放资源

        消费者消费速度慢(或停止消费了),而生产者不断往队列中投递任务,导致队列中任务累积过多

    画外音:线上执行该命令会强制执行一次fgc。另外还可以dump内存进行分析。

    三、确认是否是资源耗尽

    工具:

        pstree

        netstat

    查看进程创建的线程数,以及网络连接数,如果资源耗尽,也可能出现OOM。

     

    这里介绍另一种方法,通过

        /proc/${PID}/fd

        /proc/${PID}/task

    可以分别查看句柄详情和线程数。

     

    例如,某一台线上服务器的sshd进程PID是9339,查看

        ll /proc/9339/fd

        ll /proc/9339/task

    如上图,sshd共占用了四个句柄

        0 -> 标准输入

        1 -> 标准输出

        2 -> 标准错误输出

        3 -> socket(容易想到是监听端口)

     

    sshd只有一个主线程PID为9339,并没有多线程。

    所以,只要

        ll /proc/${PID}/fd | wc -l

        ll /proc/${PID}/task | wc -l (效果等同pstree -p | wc -l)

    就能知道进程打开的句柄数和线程数。

    希望这1分钟能帮到这位星球水友。

    展开全文
  • 解决帧动画OOM问题

    2018-11-15 12:51:56
    SurfaceView加载动画 解决OOM问题 多少帧都没问题 不会卡顿 不会卡顿
  • Java OOM问题

    千次阅读 2019-03-16 00:30:18
    关于OOM(out of memory),目前有两方面的接触。一个是在面试当中面试官会经常问到(面试造航母),另外一个就是在使用IDEA或者eclipse开发项目,项目启动过程中或者运行时候会出现OutOfMemoryError。线上运行的项目...

    阅读《深入理解Java虚拟机-JVM高级特性与最佳实践》.周志明 笔记

    关于OOM(out of memory),目前有两方面的接触。一个是在面试当中面试官会经常问到(面试造航母),另外一个就是在使用IDEA或者eclipse开发项目,项目启动过程中或者运行时候会出现OutOfMemoryError。线上运行的项目还从来没有遇到过这样的问题(但是总会遇到吧)!所以还是有必要去了解甚至是掌握相关的知识的。

    对于Java程序员来说,在虚拟机自动内存管理机制的帮助下,不再需要为每一个new操作去写配对的delete/free代码,不容易出现内存泄露和内存溢出问题,由虚拟机管理内存这一切看起来都很美好。不过,也正是因为Java程序员把内存控制的权力交给了Java虚拟机,一旦出现内存泄露和溢出方面的问题,如果不了解虚拟机是怎样使用内存的,那么排查错误将会成为一项异常艰难的工作。

       -----引自 《深入理解Java虚拟机-JVM高级特性与最佳实践》第2章

    根据自己的理解做了如下总结:

    有机会出现OOM问题的两大类情况:

    1. 来自运行时数据区

    2. 直接内存

    1.运行时数据区

      大概了解一下Java虚拟机运行时数据区的几部分组成以及可能出现的OOM情况如下

    堆(Java Heap):Java 堆是Java虚拟机所管理的内存中最大的一块,被所有线程共享的内存区域 ,用于存放对象实例,几乎所有的对象实例都在这里分配内存。这样分析来看,如果在堆中没有内存完成实例分配,并且也无法再扩展时,将会抛出OutOfMemoryError异常。比如:-Xmx:设置JVM最大堆内存大小,以及-Xms:设置JVM最小(启动时)堆的大小,这两个值设置的都很小,而且一样(防止扩展),那么只要new少许的对象出来,就会出现OutOfMemoryError。

    /**
     * @Description 模拟堆内存溢出
     * VM args: -Xms10m -Xmx10m -XX:+HeapDumpOnOutOfMemoryError
     */
    public class HeapOOM {
        static class OOMObject{
        }
        public static void main(String[] args){
            List<OOMObject> list = new ArrayList<OOMObject>();
            while(true){
                list.add(new OOMObject());
            }
        }
    }

    JavaHeapOOM

    方法区(Method Area):和Java堆一样,方法区是各个线程共享的内存区域,它用于存储已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。而运行时常量池属于方法区的一部分,用于存放编译期生成的各种字面量和符号引用。当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常。

    /**
     * @Description 运行时常量池导致内存溢出
     * VM args: -XX:PermSize=10M -XX:MaxPermSize=10M
     */
    public class RuntimeConstantPoolOOM {
        public static void main(String[] args) {
            List<String> list = new ArrayList<String>();
            int i = 0;
            while (true) {
                list.add(String.valueOf(i++).intern());
                System.out.println(i);
            }
        }
    }

     以上示例,仅仅在JDK1.6会发生OutOfMemoryError:PermGen space。

    /**
     * @Description 方法区出现内存溢出
     * VM args: -Xmx10m -Xms10m -XX:PermSize=10M -XX:MaxPermSize=10M
     */
    public class JavaMethodAreaOOM {
        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 o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                        return methodProxy.invokeSuper(o,objects);
                    }
                });
                enhancer.create();
            }
        }
        static class OOMObject{
        }
    }

    以上示例在JDK1.7环境结果为:

    JavaMethodAreaOOM1.7

    以上示例在JDK1.8环境结果为:JavaMethodArea1.8

    最后两行证实:在1.8开始已经没有永久代这一说法了,取而代之的是另一块与堆不相连的本地内存—元空间(-XX:MaxMetaspaceSize)。就以上两个示例作出说明:

    在JDK6中,方法区包含的信息,除了JIT编译生成的代码放在native memory的CodeCache区域,其他都在永久代;

    在JDK7中,Symbol的存储从PermGen移动到了native memory,并且把静态变量从instanceklass末尾(位于PermGen内)移动到了java.lang.class对象的末尾(位于Java Heap);

    在JDK8中,永久代被彻底移除,取而代之的是另一块与堆不相连的本地内存—元空间。

    Java虚拟机栈和本地方法栈:Java虚拟机栈是线程私有的,生命周期与线程相同,描述着Java方法执行的内存模型:每个方法在执行的同时会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用到执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈。如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常。如果虚拟机栈可以动态扩展,如果扩展时无法申请到足够内存就会抛出OutOfMemoryError异常。本地方法栈和虚拟机方法栈作用相似,只是本地方法栈调用的是本地方法(由其他语言实现的JVM底层方法)。

    那么有个问题,当栈空间无法继续分配时,到底是内存太小,还是已经使用的栈空间太大,其本质上描述的都是一件事。

     通过设置-Xss:栈容量。来复现一下栈溢出的情况:

    /**
     * @Description StackOverflowError
     * JVM args: -Xss2M
     */
    public class JavaVMStackSOF {
        private int stackLength=-1;
        public void stackLeak(){
            stackLength++;
            stackLeak();
        }
        public static void main(String[] args) throws Throwable{
            JavaVMStackSOF oom= new JavaVMStackSOF();
            try{
                oom.stackLeak();
            }catch (Throwable e){
                System.out.println("Stack length:" +oom.stackLength);
                throw e;
            }
        }
    }

    StackOverflowOOM

    实验结果表明:在单线程下,无论是由于栈帧太大,还是虚拟机栈容量太小,当内存无法分配的时候,虚拟机抛出的都是StackOverflowError。-----引自 《深入理解Java虚拟机-JVM高级特性与最佳实践》第2章

    /**
     * @Description 创建线程导致内存溢出
     * JVM args: -Xss2M
     */
    public class JavaVMStackOOM {
        private void dontStop() {
            while (true) {
    
            }
        }
    
        public void stackLeakByThread() {
            while (true) {
                Thread thread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        dontStop();
                    }
                });
                thread.start();
            }
        }
    
        public static void main(String[] args) throws Throwable {
            JavaVMStackOOM oom = new JavaVMStackOOM();
            oom.stackLeakByThread();
        }
    }
    

    JavaStackOOM

    通过以上的示例,说明一个问题,高版本的JDK可靠性更高了,如果是从头开始做一个项目,最好还是使用当前比较新而且稳定的JDK版本。

    程序计数器:运行时数据区还有程序计数器的存在,线程私有,一块很小的内存,Java规范中没有没有规定任何OOM情况。

    还有一种内存溢出就是直接内存溢出

    直接内存并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存 区域。但是这部分内存也被频繁地使用,而且也能导致OOM。在JDK1.4之后,新加入了NIO(new Input/Output),引入了一种基于通道(channel)和缓冲区(Buffer)的I/O方式,它可以使用Native函数直接分配内存,然后通过存储在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。这样可以显著提高性能,避免了Java堆和Native堆中来回复制数据。DirectMemory容量可以通过-XX:MaxDirectMemorySize指定,如果不指定则默认与Java堆最大值(-Xmx指定)一样。

    /**
     * @Description 直接内存溢出
     * JVM args: -XX:MaxDirectMemorySize=10M
     */
    public class DirectMemoryOOM {
        private static final int _1MB = 1024 * 1024;
    
        public static void main(String[] args) throws Exception {
            Field unsafefield = Unsafe.class.getDeclaredFields()[0];
            unsafefield.setAccessible(true);
            // 返回指定对象上由此Field表示的字段的值。
            // 如果该对象具有原始类型,则该值将自动包装在对象中。
            Unsafe unsafe = (Unsafe) unsafefield.get(null);
            while (true) {
                unsafe.allocateMemory(_1MB);
            }
        }
    }
    

    DirectMemoryOOM

    关于1.8虚机运行时内存划分的改动参考,这位博主讲的很详细很明白。

     

     

    展开全文
  • Java OOM问题如何排查

    千次阅读 2020-06-15 12:07:40
    文章目录OOM 问题什么是OOM导致OOM问题的原因排查手段实战MAT分析 OOM 问题 什么是OOM OOM为out of memory的简称,来源于java.lang.OutOfMemoryError,指程序需要的内存空间大于系统分配的内存空间,OOM后果就是程序...
  • 1. 什么是OOMOOM,全称“Out Of Memory”,翻译成中文就是“内存用完了”,来源于java.lang.OutOfMemoryError。 看下关于的官方说明: Thrown when the Java Virtual Machine cannot allocate an object because ...
  • 线上OOM问题排查

    万次阅读 2021-06-26 14:59:32
    java -Xms48m -Xmx48m -XX:+HeapDumpOnOutOfMemoryError XX:HeapDumpPath=./heapdump.prof -jar 使用jprofiler 查看dump文件 与及 call tree 分析
  • Android解决图片OOM问题

    2015-10-22 14:41:53
    Android解决图片OOM问题的Demo小实例,里面有注释,初学者应该能看懂
  • OOM问题排查

    2018-05-11 13:39:51
    一次OOM排查过程 https://blog.csdn.net/john8169/article/details/55802651
  • 解决Android加载图片出现的OOM问题
  • Redis OOM问题排查

    千次阅读 2019-11-16 11:50:02
    看到Redis报了OOM的错误,而且服务响应速度非常慢,页面上丢了很多数据,赶紧起来查看问题。 2. 问题排查 我们的系统架构是双边双活的,两个DC(Primary和GSB)都会有数据写进来,通过API把数据存到数据库(双边...
  • 最近查找了很多关于OOM,甚至于Java内存管理以及JVM的相关资料,发现这方面的东西太多了,竟有一种眼花缭乱的感觉,要想了解全面的话,恐非一篇文章能说清的,因此按照自己的理解整理了一篇,剩下的还需要继续学习。...
  • OOM

    千次阅读 2019-01-22 16:38:16
    OOM问题总结什么是OOM为什么会OOMOOM的类型OOM处理方式 什么是OOM OOM ,全称"OutOfMemery",中文名称“内存不够用”。 很长时间以来,很多人都知道jvm内存调优是java知识中的重要组成部分,但是缺乏应用...
  • 线上OOM问题实战

    千次阅读 2019-03-26 11:43:30
    遇到这种错误,往往很难知道是哪里出错,我去年有记录定位OOM问题的文章,刚好重温一下:线上java.lang.OutOfMemoryError问题定位三板斧 先不着急重启,先看看内存情况: top 查看java运行的pid jmap -heap pid ...
  • Jasperreports OOM问题处理

    千次阅读 2018-01-29 17:13:56
    主要导致OOM问题有如下两种: jasper模板文件设计不合理导致Jasperreports进入死循环 需要转换的文件确实很大,超过了系统所支持的内存范围 此前就有遇到过上述情况导致系统不可用的情况,这明显影响了程序的...
  • OOM问题定位方法

    千次阅读 2018-09-15 14:46:00
    线上内存OOM问题是最难定位的问题,最常见的原因: (1)本身资源不够 (2)申请的太多 (3)资源耗尽 某服务器上部署了Java服务,出现OutOfMemoryError,请问有可能是什么原因,问题应该如何定位? 解决思路:...
  • Flume OOM 问题

    千次阅读 2017-03-29 17:38:47
    Spark,Hadoop交流群,群QQ号:521066396,欢迎加入共同学习,一起进步~1、问题使用Flume遇到如下报错:java.lang.OutOfMemoryError: GC overhead limit exceeded或者:java.lang.OutOfMemoryError: Java heap space...
  • 关于ThreadPool抛出OOM问题案例为什么会OOM 案例 最近在学习Java调优,有个案例是ThraadPool导致OOM,在不了解线程池的情况很难看出问题来。 代码片. package com.example.demo; import java.util.concurrent....
  • OOM问题总结

    千次阅读 2015-03-23 15:59:57
    OutOfMemoryError(OOM)就是常说的内存泄露问题。为了能够使Android应用程序能够高效快速地运行,所以Android的每个应用程序都会用一个专有的Davilk虚拟机(Android L 上谷歌使用了传闻已久的ART来代替Dalvik)实例...
  • Spark OOM问题

    2019-09-10 08:44:05
    目录 堆内存OOM Driver heap Executor heap 堆外内存OOM Spark中的OOM问题主要包括以下两种情况: map执行中内存溢出: map执行中内存溢出代表了所有map类型的操作,包括:flatMap,filter,mapPatitions等 shuffle...
  • 一次线上OOM问题排查

    千次阅读 2019-08-05 21:29:22
    1、出现OOM问题了,脑袋里第一反应就是项目中出现内存泄露或者内存溢出了。先登录ELK,根据关键词 “java.lang.OutOfMemoryError” 进行搜索,果然发现有OOM错误日志。 org.springframework.scheduling.q...
  • 主要给大家介绍了一次OOM问题排查过程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
  • TensorFlow—OOM问题

    2020-03-27 11:43:59
    TensorFlow OOM 问题 记一个关于TensorFlow的小笔记: 使用model 在 TensorFlow 2.0 中每次使用完 keras 中的 model import tensorflow as tf model = tf.keras.models.load_model("model.h5") prediction=model....

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 118,037
精华内容 47,214
关键字:

oom问题是啥