1. The cause of the event during the project, the Memory Monitor window of Android Studio was used to observe the use of the program, and found that when the program exited, a portion of the memory should be freed up, knowing that there should be a memory leak in the program. In order to discover the memory leaks in the program, I switched the IDE tool to eclipse, which installed a memory leak analysis tool mat, specifically how to analyze the memory leaks with the mat Google, I put myself to find a memory leak place to post
As you can see, there is about 24M of memory being mview (in fact it is really a fragment) this variable is held, resulting in Java garbage collection will not be recycled. Trace to the top, the root of GC root is a cache object inside the volley library Mcachequeue holds mview, which causes the system not to be recycled. Found the reason, the solution is good. There are two solutions, one is to empty the Volle cache object, the other is to put mlistener empty, do not have a reference to hold the Mview object. 2. How does the code let the volley cache object hold the Mview object? The key code is as follows, removing some of the logic, looking only at the anonymous inner class part
Public cchttprequest (Final String URL, final map<string, string> params, final Ccapicallback callback) { C2/>mrequest = new Httpstringrequest (HttpGsonRequest.Method.POST, url) { @Override protected Map<string, String> Getparams () { return params; } @Override protected void Onresponse (String s) {
<pre name= "code" class= "java" > <span style= "White-space:pre" ></span>if (null! = callback) { Callback.onresponse (data.tostring (), Hasservertime, servertime); }
} @Override protected void Onerrorresponse (Exception e) {if (null! = callback) {//System error returned-1 callback.onerror (createerrorm Essage ( -1, E.getmessage ())); } } }; }
Objects that are held by the volley cache areNew Httpstringrequest An instance of this anonymous class object, why the parameters in the methodFinal Ccapicallback Callback This parameter is held in the newly created anonymous interior? 3. A simple example that explains the relationship between the Java anonymous class and the external class
Write a simple Hello.java file that includes an anonymous class with an internal class demo
public class Hello{private string mname= "37785612"; class Demo{public void Show () {}}public void Showdemo (final String s) {n EW Demo () {public void Show () {System.out.println ("s=" +s); System.out.println ("name=" +mname);} . Show ();}}
After executing javac Hello.java compilation, the following class files are generated in the same directory, Hello.class,hello$1.class,hello$demo.class. Hello.class is the class file for our source file Hello, Hello$1.class is the class file for the anonymous class in the Showdemo () method, hello$ Demo.class is the class file of the internal class demo, here we mainly analyze Hello.class and hello$1.class. Execute the command javap-v Hello, the compiled part of the code is as follows:
{public Hello (); Code: stack=2, Locals=1, args_size=1 0:aload_0 1:invokespecial#2;//method java/lang/object. " <init> ":() V 4:aload_0 5:ldc#3;//string 37785612 7:putfield#1;//field mname:ljava/lang/string ; 10:return linenumbertable: line 1:0 line 2:4 line 3:10public void Showdemo (java.lang.String); Code: stack=4, locals=2, args_size=2 0:new#4;//class hello$1 3:dup 4:aload_0 5:aload_1 6:invokespecial#5,//method hello$1. " <init> ":(Lhello; ljava/lang/string;) v 9:invokevirtual#6;//method hello$1.show: () v 12:return linenumbertable: Line 8:0 line 14:12static java.lang.String access$000 (Hello); Code: stack=1, Locals=1, args_size=1 0:aload_0 1:getfield#1;//field mname:ljava/lang/string; 4:areturn linenumbertable: line 1:0}
Here's a way to seeaccess$000 (Hello)Is that we do not appear in the source file, and after the compilation will be more This method, it is actually the return variable mname value, will say how this method will be used
To continue executing the command javap-v hello$1, the compiled part of the code is as follows
{Final java.lang.String val$s;final Hello this$0; Hello$1 (Hello, java.lang.String); code:stack=2, locals=3, args_size=3 0:aload_0 1:aload_1 2:putfield#1; Field This$0:lhello; 5:aload_0 6:aload_2 7:putfield#2; Field val$s:ljava/lang/string; 10:aload_0 11:aload_1 12:invokespecial#3; Method Hello$demo. " <init> ":(Lhello;) V 15:return linenumbertable:line 8:0public Void Show (); Code:stack=3, Locals=1, args_size=1 0:getstatic#4; Field Java/lang/system.out:ljava/io/printstream; 3:new#5; Class Java/lang/stringbuilder 6:dup 7:invokespecial#6; Method Java/lang/stringbuilder. " <init> ":() V 10:ldc#7; String s= 12:invokevirtual#8; Method java/lang/stringbuilder.append: (ljava/lang/string;) Ljava/lang/stringbuilder; 15:aload_0 16:getfield#2; Field val$s:ljava/lang/string; 19:invokevirtual#8; Method java/lang/stringbuilder.append: (ljava/lang/string;) Ljava/lang/stringbuilder; 22:invokevirtual#9; Method Java/lang/stringbuiLder.tostring: () ljava/lang/string; 25:invokevirtual#10; Method java/io/printstream.println: (ljava/lang/string;) V 28:getstatic#4; Field Java/lang/system.out:ljava/io/printstream; 31:new#5; Class Java/lang/stringbuilder 34:dup 35:invokespecial#6; Method Java/lang/stringbuilder. " <init> ":() V 38:ldc#11; String name= 40:invokevirtual#8; Method java/lang/stringbuilder.append: (ljava/lang/string;) Ljava/lang/stringbuilder; 43:aload_0 44:getfield#1; Field This$0:lhello; 47:invokestatic#12; Method hello.access$000: (Lhello;) ljava/lang/string; 50:invokevirtual#8; Method java/lang/stringbuilder.append: (ljava/lang/string;) Ljava/lang/stringbuilder; 53:invokevirtual#9; Method java/lang/stringbuilder.tostring: () ljava/lang/string; 56:invokevirtual#10; Method java/io/printstream.println: (ljava/lang/string;) V 59:return linenumbertable:line 10:0 line 11:28 Lin E 12:59}
We can see that this anonymous class has two more member variablesfinal java.lang.String val$s andfinal Hello this$0; look at the constructor of this anonymous class.hello$1 (Hello, java.lang.String); exactly two member variables are assigned. This$0 points to a reference to an external class object, val$s points to the memory reference to the parameter s of Method Showdemo (final String s). Look at how anonymous classes are accessing member variables of external classes. Take a look at these lines of assembly code:
43:aload_0 44:getfield#1;//field This$0:lhello; 47:invokestatic#12; Method hello.access$000: (Lhello;) ljava/lang/string;
43, call the This object within anonymous, 44, get the THIS$0 member variable of the anonymous class, that is (Hello object) 47 static method of calling Hellostatic java.lang.String access$000 (Hello); Gets the value of member MnameHere we can summarize the relationship between anonymous and external classes and the relationship of method parameters:1. An anonymous class will have a member variable that points to a reference to an external class2. If an anonymous class is to use one of the parameters in the method, the corresponding parameter of the method must be final, which seems to be mandatory for Java. and a member variable in an anonymous class points to the same storage area that the parameter object points to3. Anonymous class access to members of an external class is accessed through a static method call, and if access to multiple members of an external class is required, multiple static methods are generated in the external class to provide access to the member variables of the external class to the anonymous class. 4. Find out the real reasonfrom the above about the relationship between the anonymous class and the external class, we can find that the callback in my code holds an external object, a layer fallback, the bottom callback object holds an external reference, and just this external object holds a Mlistener object , and the Mlistener inner class object holds an external object, which in turn holds the Mview, causing the memory leak to occur when the program exits because the volley cache is not released and the Mview object is not garbage collected.
Resolving memory leaks clearer understanding of the relationship between Java anonymous classes and external classes