V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
limerence12138
V2EX  ›  Android

Bitmap createBitmap 不分配内存问题

  •  
  •   limerence12138 · 2021-08-04 00:52:58 +08:00 · 9406 次点击
    这是一个创建于 1239 天前的主题,其中的信息可能已经有所发展或是发生改变。

    事情是这样的,我的同事让我帮他看这个代码为什么不分配内存,我看了两天没啥结果,水平不够就来问了

    binding.button.setOnClickListener {
        repeat(1000) {
            list.add(Bitmap.createBitmap(10240, 1024 / 4, Bitmap.Config.ARGB_8888))
        }
    }
    

    通过 Android studio 的 profiler 查看内存根本没动静,dump 出来看到都 bitmap 的 Native size 都已经 9 个 G 了(亲测),每个 java bitmao 也都有 NativePtr,还不是相同的,但是这应该是 bug 或者是虚拟内存空间的?搞不懂,然后看了两天代码,基础有点差,最后只看到确实分配了内存

    sk_sp<Bitmap> Bitmap::allocateHeapBitmap(size_t size, const SkImageInfo& info, size_t rowBytes) {
        // 应该是这里吧??
        void* addr = calloc(size, 1);
        if (!addr) {
            return nullptr;
        }
        return sk_sp<Bitmap>(new Bitmap(addr, size, info, rowBytes));
    }
    

    昨天也是搞到几点才睡觉,救😭

    13 条回复    2021-08-05 09:33:40 +08:00
    Cabana
        1
    Cabana  
       2021-08-04 08:58:39 +08:00 via iPhone
    你看的是不是 java 内存占用呀?
    hnbcinfo
        2
    hnbcinfo  
       2021-08-04 09:02:57 +08:00
    看列表头像,我以为我发的帖子呢。[狗头]
    maokabc
        3
    maokabc  
       2021-08-04 09:21:20 +08:00 via Android
    java 层 bitmap 就是个壳,实际是那个 nativePtr 对应的 native 对象,java 对象没被回收 native 层对应的内存也不会被释放。jni 常见的方式,用 long 存储 native 指针。
    limerence12138
        4
    limerence12138  
    OP
       2021-08-04 09:54:37 +08:00
    @maokabc 看的 profiler 显示的内存,就是那个 memory 里显示的总的,包括 native,java 堆,stack 啥的
    @Cabana 这我知道,现在问题是没被回收,分配的内存去哪儿了,分配了 1000 次这么大的都没问题?
    janus77
        5
    janus77  
       2021-08-04 13:52:22 +08:00 via iPhone
    新版本特意改成这样的,为了防止 oom,现在手机内存可大了,用这么多正常
    r00tt
        6
    r00tt  
       2021-08-04 13:53:00 +08:00
    因为你把 bitmap 加入到 list 里面去了,自然不会回收
    limerence12138
        7
    limerence12138  
    OP
       2021-08-04 15:22:54 +08:00
    @janus77 能到 10 几个 G,你觉得可能吗,超过物理限制了都。。
    @r00tt 我无语了,你看清楚啊,我故意不让它回收,现在是在问内存分配的问题
    janus77
        8
    janus77  
       2021-08-04 15:50:15 +08:00
    @limerence12138 #7 当然可以,native 内存理论上可以达到你手机的物理上限,现在主流手机都是 8G 了 旗舰 12G 9G 很正常啊
    r00tt
        9
    r00tt  
       2021-08-04 16:21:04 +08:00
    @limerence12138 仔细看了下,确实是虚拟内存,我按照你的代码,把 repeat 改成了 10000,程序依旧正常。htop 看了下 VIRT 已经 100 多 G 了,实际上应用占用内存才几百 M 。alloc 分配的是虚拟内存,实际能用的取决于 MMU 吧,你这 1k 个 bitmap 又没同时展示出来,所以不会 oom 的
    limerence12138
        10
    limerence12138  
    OP
       2021-08-04 22:31:40 +08:00
    @janus77 动一下手不难呀兄弟

    @r00tt 我往这个方向猜了没去试,我刚也 showmap pid 看了一下,点一下 virtual size 确实增加了 10G 左右,看起来就是 alloc 的实现方式是这样的,看来还是基础不牢呀
    hyb1996
        11
    hyb1996  
       2021-08-04 23:09:21 +08:00 via Android
    只要你不用(不读,不写),物理内存就不会实际分配,你分配时读一下试试
    r00tt
        12
    r00tt  
       2021-08-05 01:07:03 +08:00
    @limerence12138 还是跟系统的配置有关系的,我 cat 了下 /proc/sys/vm/overcommit_memory 这个文件,值是 1,文档上说是 “always overcommit, never check ” 所以可以不停分配而没有 OOM,再者,你只是分配这么多 Bitmap,实际上并没有同时 show 出来
    john6lq
        13
    john6lq  
       2021-08-05 09:33:40 +08:00 via iPhone
    https://blog.csdn.net/pansaky/article/details/90267374
    内存管理(原理及机制,linux/Android 虚拟内存管理)
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5713 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 02:59 · PVG 10:59 · LAX 18:59 · JFK 21:59
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.