JavaScript is not currently enabled, but is required for full CodeSonar manual search and browse functionality.

If you are viewing this file in your hub's Web GUI, enable JavaScript in your browser: you will also need it for GUI functionality.

If you opened this file directly from disk, your browser may be directly suppressing JavaScript functionality: certain browsers perform this suppression on local files (but not files delivered by web servers) for security reasons.

CodeSonar® 9.2p0 CONFIDENTIAL CodeSecure Inc
Java


JAVA.ALLOC.LEAK.ANDROID : Android Leak (Java)

Summary

This checker identifies memory leaks in Android code. They occur every time an operating system managed object is stored into a data structure that might survive its life-cycle. As a consequence, the managed object will not be garbage-collected before the data structure. This results in increased memory consumption or application crash.

Resources may be leaked. Includes the following scenarios

Properties

Class Name Android Leak (Java)
Significance reliability
Mnemonic JAVA.ALLOC.LEAK.ANDROID
Categories
CWE CWE:664 Improper Control of a Resource Through its Lifetime
Availability Available for Java and Kotlin.

Android Only. Warnings of this class will only be reported in Android code: that is, code that uses the Android API.

Enabling Checks for this warning class are enabled by default. To disable them, add the following WARNING_FILTER rule to the project configuration file.
WARNING_FILTER += discard class="Android Leak (Java)"

Example

// InnerClassActivity.java
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class InnerClassActivity extends AppCompatActivity {  /* "Android Leak (Java)" 
                       * warning issued here: the anonymous inner class that implements the Runnable 
                       * is not static and consequently points to the outer object, which in this case is an activity. 
                       * The latter will never be reclaimed while the potentially long computation inside 
                       * the run() method is performed. CodeSonar also observes that that computation 
                       *  contains a loop and so is suspiciously long.
                       */ 
  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_inner_class);

      Thread connectionThread = new Thread(new Runnable() {
          public void run ( ) {
              for (long l1 = 0L; l1 < 1000000000L; l1++)
                  for (long l2 = 0L; l2 < 1000000000L; l2++)
                      for (long l3 = 0L; l3 < 1000000000L; l3++) {}
          }
      });
      connectionThread.start();
  }
}
// StaticFieldActivity.java 
import android.app.Activity;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

public class StaticFieldActivity extends AppCompatActivity { /* "Android Leak (Java)" 
                               * warning issued here: static fields are never garbage-collected, so 
                               * nothing reachable from a static field can be garbage-collected. In  
                               * this case, the StaticFieldActivity is made reachable from the static field 
                               * and hence gets leaked. 
                               */ 

  private static Wrapper wrapper;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_static_field);
      wrapper = new Wrapper();
      wrapper.setActivity(this);
  }

  private static class Wrapper {
    private Activity activity;

    public void setActivity(Activity activity) {
        this.activity = activity;
    }
  }
}
//ServiceCallbackActivity.java
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

public class ServiceCallbackActivity extends AppCompatActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_service_callback);
      Connector connector = new Connector(this);
      connector.go();
  }
}
// Connector.java
import android.app.Service;
import android.content.Context;
import android.net.ConnectivityManager;

public class Connector implements ConnectivityManager.OnNetworkActiveListener { 

  public Connector(Context context) {/* "Android Leak (Java)" 
                               * warning issued here: the listener attached to the ConnectivityManager points to 
                               * a context which is actually an activity passed when a new Connector is created
                               * inside ServiceCallbackActivity.onCreate(). Since listeners become reachable from
                               * the observed object, which is a never garbage-collected system service, that activity gets leaked. 
                               */ 
      this.context = context;
  }

  public void go() {
      ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Service.CONNECTIVITY_SERVICE);
      manager.addDefaultNetworkActiveListener(this);
  }

  private Context context;

  @Override
  public void onNetworkActive() { ... }
}

For InnerClassActivity, a solution would be to define the Runnable as a separate, named class. That class can well be an inner class, as long as it is defined static:

// InnerClassActivity.java (after adjustment)
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class InnerClassActivity extends AppCompatActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_inner_class);
      Thread connectionThread = new Thread(new MyRunnable());
      connectionThread.start();
  }

  private static class MyRunnable implements Runnable {
    public void run ( ) {
        for (long l1 = 0L; l1 < 1000000000L; l1++)
            for (long l2 = 0L; l2 < 1000000000L; l2++)
                for (long l3 = 0L; l3 < 1000000000L; l3++) {}
    }
  }
}

For StaticFieldActivity, a solution would be to detach the wrapped activity when it is destroyed and hence its life-cycle has finished.

// StaticFieldActivity.java (after adjustment)
import android.app.Activity;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

public class StaticFieldActivity extends AppCompatActivity {

  private static Wrapper wrapper;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_static_field);

    wrapper = new Wrapper();
    wrapper.setActivity(this);
  }

  @Override
  protected void onDestroy() {
    wrapper.setActivity(null);
    super.onDestroy();
  }
  
  //...
}

For ServiceCallbackActivity, a solution would be to pass to the Connector only the information that it really needs. In this case, it does not really need the whole context, but only the ConnectivityManager.

// ServiceCallbackActivity.java (after adjustment)
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
 
public class ServiceCallbackActivity extends AppCompatActivity {
 
  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_service_callback);
      Connector connector = new Connector((ConnectivityManager) getSystemService(Service.CONNECTIVITY_SERVICE));
      connector.go();
  }
}
// Connector.java (after adjustment)
import android.app.Service;
import android.content.Context;
import android.net.ConnectivityManager;
 
public class Connector implements ConnectivityManager.OnNetworkActiveListener {
 
  public Connector(ConnectivitytManager manager) {
      this.manager = manager;
  }
 
  public void go() {
      manager.addDefaultNetworkActiveListener(this);
  }
 
  private ConnectivityManager manager;
 
  @Override
  public void onNetworkActive() { ... }
}

Relevant Configuration File Parameters

The following configuration file parameters affect checks for this warning class.

 

To report problems with this documentation, please visit https://support.codesecure.com/.