java 内部类的内存图_Java中内部类的内存泄露问题

package com.example.temptemp;

import android.app.Activity;

import android.os.Bundle;

import android.util.Log;

import android.widget.TextView;

public class SecondActivity extends Activity {

byte[] bigData = new byte[10 * 1024 * 1024];

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

((TextView) findViewById(R.id.txt)).setText("SecondActivity");

}

@Override

protected void onDestroy() {

super.onDestroy();

// test();

test2();

}

private void test() {

new Thread() {

@Override

public void run() {

super.run();

Log.e("SS", "start");

try {

Thread.sleep(15000);

} catch (InterruptedException e) {

e.printStackTrace();

}

Log.e("SS", "end");

}

}.start();

}

private static void test2() {

new Thread() {

@Override

public void run() {

super.run();

Log.e("SS", "start");

try {

Thread.sleep(15000);

} catch (InterruptedException e) {

e.printStackTrace();

}

Log.e("SS", "end");

}

}.start();

}

}

这是一个简单的Activity,里面有两个简单的方法,test()和test2(),test()和test2()的唯一区别就是一个是静态的,一个非静态的。

同时这个类有个成员变量bigData,主要是分配10M的内存,便于查看内存的变化。

测试方法:

只调用test方法:当Activity销毁后,发现只有等线程结束后,该Activity才能被回收;

只调用test2方法:当Activity销毁后,发现该Activity能立即被回收。

原因就是Java中内部类(匿名内部类也一样)会有宿主类的强引用。也就是this变量的来源。是编译默认行为。用javap查看class文件可以看出。

Compiled from "SecondActivity.java"

class com.example.temptemp.SecondActivity$1 extends java.lang.Thread {

final com.example.temptemp.SecondActivity this$0;

com.example.temptemp.SecondActivity$1(com.example.temptemp.SecondActivity);

Code:

0: aload_0

1: aload_1

2: putfield #10 // Field this$0:Lcom/example/temptemp/SecondActivity;

5: aload_0

6: invokespecial #12 // Method java/lang/Thread."":()V

9: return

public void run();

Code:

0: aload_0

1: invokespecial #20 // Method java/lang/Thread.run:()V

4: ldc #22 // String SS

6: ldc #24 // String start

8: invokestatic #26 // Method android/util/Log.e:(Ljava/lang/String;Ljava/lang/String;)I

11: pop

12: ldc2_w #32 // long 15000l

15: invokestatic #34 // Method java/lang/Thread.sleep:(J)V

18: goto 26

21: astore_1

22: aload_1

23: invokevirtual #38 // Method java/lang/InterruptedException.printStackTrace:()V

26: ldc #22 // String SS

28: ldc #43 // String end

30: invokestatic #26 // Method android/util/Log.e:(Ljava/lang/String;Ljava/lang/String;)I

33: pop

34: return

Exception table:

from to target type

12 18 21 Class java/lang/InterruptedException

}

注意看this$0,就是对宿主类的引用。

结论:在内部类中这种内存泄露一般很容易被忽略,比如经常会在Activity onDestroy中进行一些回收,或者同步工作,这时也应当避免做耗时的操作,就算耗时操作用匿名内部类的Thread来做,也同样可能造成泄露。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值