57

When using the console of AndroidStudio on my app it shows:

W/System: A resource failed to call release.

Sometimes it is said multiple times. I know what it means but I've checked the almost 2k lines of code multiple times but I'm clueless what I'm missing to close/release.

Is there any way to expand on this information from the console? or how would you do to target what the resource is or when it fails to close? Any ideas are welcome. Thanks.

starball
  • 20,030
  • 7
  • 43
  • 238
Emiliho Stifler
  • 681
  • 1
  • 5
  • 5

5 Answers5

42

The answer from @guest works, but you can achieve the exact same thing without resorting to reflection using Strict Mode. Specifically, something like:

StrictMode.setVmPolicy(new VmPolicy.Builder()
                 .detectLeakedClosableObjects()
                 .penaltyLog()
                 .build());

In general, strict mode can do much more for you though (see link above to doc), and all you need to do for a default setup is:

StrictMode.enableDefaults();  # <-- This includes warning on leaked closeables

To enable strict mode "as soon as possible" you can add either of the above code options to the constructor of your application class, e.g.:

public class MyApp extends Application {

    public MyApp() {
        if(BuildConfig.DEBUG)
            StrictMode.enableDefaults();
    }

}

Note that in addition to just creating the class above, you need to tell Android that you have created a custom application class in the AndroidManifest.xml (so that an instance of it gets created when your application process starts, instead of Android creating the default Application class). You need to add/modify the android:name attribute of the <application> tag to point to the fully resolved package path of your custom application class (MyApp in this case):

<application
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:name="com.example.app.MyApp"  <-- IMPORTANT PART: ADAPT FOR YOUR ACTUAL PROJECT
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
pallgeuer
  • 1,216
  • 1
  • 7
  • 17
  • thanks. hadn't found that due to cs.android.com reference search not being aware of that caller for some reason – guest Jan 04 '21 at 18:56
  • I don't have any class extending Application. Should I put this in each Activity? – Luis A. Florit May 09 '21 at 21:40
  • 1
    @LuisA.Florit You could do that, but it's error prone and not a particularly good solution. I recommend creating a class extending Application like I showed, as it may be useful for other things as well (e.g. configuring LeakCanary). Doc: You can provide your own implementation by creating a subclass and specifying the fully-qualified name of this subclass as the "android:name" attribute in your AndroidManifest.xml's tag. The Application class, or your subclass of the Application class, is instantiated before any other class when the process for your application is created. – pallgeuer May 10 '21 at 11:57
  • @pallgeuer Sorry, I did not understand the "Doc" part. I created the App class with your suggested content. Should I also include that in the manifest? Is this mandatory? – Luis A. Florit May 10 '21 at 12:48
  • 1
    @LuisA.Florit Refer to the edit. Hopefully it's clearer now. – pallgeuer May 12 '21 at 09:00
  • @pallgeuer Perfect! Now I see the difference. Thanks! – Luis A. Florit May 12 '21 at 17:54
  • Thanks, this is helpful. – King Of The Jungle Dec 07 '21 at 18:19
  • Thanks for the tip. Is there a way to catch this logs returned by StrictMode and send them to some logging library. – Sergio Jun 07 '22 at 13:05
  • 1
    @Sergio Yes, instead of using `penaltyLog()` you can use other options such as `penaltyListener()`, which allows a custom callback for example. – pallgeuer Jun 07 '22 at 14:48
23

This message comes from dalvik.system.CloseGuard. When debugging, you can set it up to create stack traces as you create resources, so that you can track down what objects aren't being closed.

It's not part of the framework API, so I'm using reflection to turn that on:

try {
    Class.forName("dalvik.system.CloseGuard")
            .getMethod("setEnabled", boolean.class)
            .invoke(null, true);
} catch (ReflectiveOperationException e) {
    throw new RuntimeException(e);
}

more info: https://wh0.github.io/2020/08/12/closeguard.html

guest
  • 6,450
  • 30
  • 44
  • 5
    This is the true answer as it lets you find what is directly causing the message. LeakCanary is a great tool, but doesn't help with resolving this kind of a message because the problem object is usually not one of the auto-watched types (e.g. Activity, Fragment, etc) – pallgeuer Oct 15 '20 at 16:31
  • @pallgeuer what do u think about android profiler? In box Android profiler can detect? i used this answer and its work for me but i interesting other. – Fortran Dec 16 '20 at 21:42
  • 3
    @Fortran I don't think the Android profiler would help much in detecting specific leaks reported by "W/System: A resource failed to call release" – pallgeuer Dec 17 '20 at 12:21
  • This or my solution both can go "anywhere", but if you want to make sure it gets called as soon as possible you can put it in your Application class constructor – pallgeuer Jan 05 '21 at 09:13
  • 1
    Very elegant and helpful. Thank you! – DmitryO. Jul 04 '21 at 10:29
17

I don't think that you can get any more information out of Logcat.

The memory view of the Android Profiler is probably a good place to start. Looking at it while using your app should give you an idea of what actions cause memory to be allocated and not released. You can also select sections from the timeline and drill down to specific allocations by class.

Alternatively LeakCanary is a great library to detect memory leaks.

  • Thank you. In fact, I discovered the Profiler tool a while ago but it's nice to see that I'm on the right track. Can't upvote you cause I'm new though :( – Emiliho Stifler Sep 27 '19 at 06:40
4

Fixed it by removing a function call that called itself through another function thereby making an infinite loop of calls to itself

Javier Z
  • 41
  • 1
1

Late answer, but it may be useful to someone else:

I faced the same error, but I forgot I had my VPN running in the background. Disconnecting the VPN did the trick for me. This is to say it may be due to resources unrelated to your app or IDE you may want to check, like an antivirus, VPN, etc.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Stadmina
  • 121
  • 1
  • 8