导航:首页 > 操作系统 > android避免内存泄露

android避免内存泄露

发布时间:2022-10-01 15:19:20

android scrollview内存溢出怎么解决

android scrollview内存溢出通常是由内存泄露导致。
1、内存泄露导致
由于我们程序的失误,长期保持某些资源(如Context)的引用,垃圾回收器就无法回收它,当然该对象占用的内存就无法被使用,这就造成内存泄露。
Android 中常见就是Activity被引用在调用finish之后却没有释放,第二次打开activity又重新创建,这样的内存泄露不断的发生,则会导致内存的溢出。
Android的每个应用程序都会使用一个专有的Dalvik虚拟机实例来运行,它是由Zygote服务进程孵化出来的,也就是说每个应用程序都是在属于自己的进程中运行的。Android为不同类型的进程分配了不同的内存使用上限,如果程序在运行过程中出现了内存泄漏的而造成应用进程使用的内存超过了这个上限,则会被系统视为内存泄漏,从而被kill掉,这使得仅仅自己的进程被kill掉,而不会影响其他进程.
2、占用内存较多的对象
保存了多个耗用内存过大的对象(如Bitmap)或加载单个超大的图片,造成内存超出限制。
使用方法比较简单:
· 选择DDMS视图,并打开Devices视图和Heap视图
· 点击选择要监控的进程,比如:上图中我选择的是system_process
· 选中Devices视图界面上的"update heap" 图标
· 点击Heap视图中的"Cause GC" 按钮(相当于向虚拟机发送了一次GC请求的操作)
在Heap视图中选择想要监控的Type,一般我们会观察dataobject的 total size的变化,正常情况下total size的值会稳定在一个有限的范围内,也就说程序中的代码良好,没有造成程序中的对象不被回收的情况。如果代码中存在没有释放对象引用的情况,那么data object的total size在每次GC之后都不会有明显的回落,随着操作次数的增加而total size也在不断的增加。(说明:选择好data object后,不断的操作应用,这样才可以看出total size的变化)。如果totalsize确实是在不断增加而没有回落,说明程序中有没有被释放的资源引用。那么我们应该怎么来定位呢?
Android中内存泄露定位
通过DDMS工具可以判断应用程序中是否存在内存泄漏的问题,那又如何定位到具体出现问题的代码片段,最终找到问题所在呢?内存分析工具MAT Memory Analyzer Tool解决了这一难题。MAT工具是一个Eclipse 插件,同时也有单独的RCP 客户端,MAT工具的解析文件是.hprof,这个文件存放了某进程的内存快照。MAT工具定位内存泄漏具体位置的方法如下:
① 生成.hprof文件。Eclipse中生成.hprof文件的方法有很多,不同Android版本中生成.hprof的方式也稍有差别,但它们整体思路是一样的。我们在DDMS界面选中想要分析的应用进程,在Devices视图界面上方的一行图标按钮中,同时选中“Update Heap”和“Dump HPROF file”两个按钮,这时DDMS将会自动生成当前选中进程的.hprof文件。
② 将.hprof 文件导入到MAT工具中,MAT工具会自动解析并生成报告,点击“Dominator Tree”按钮,并按包分组,选择已定义的包类点右键,在弹出的菜单中选择List objects﹥With incoming references,这时会列出所有可疑的类。右键点击某一项,并选择Path to GC Roots﹥excludeweak/soft references,MAT工具会进一步筛选出跟程序相关的所有内存泄漏的类。这样就可以追踪到某一个产生内存泄漏的类的具体代码中。
使用MAT内存分析工具查找内存泄漏的根本思路是找到哪个类的对象的引用没有被释放,然后分析没有被释放的原因,最终定位到代码中哪些片段存在着内存泄漏。

② android webview怎样开辟新的进程避免内存泄露

Android中的WebView组件,内存泄漏的问题一直没有非常有效的解决方案。只能去自己集成腾讯的X5内核。

③ android webview怎样开辟新的进程避免内存泄露

使用crosswalk
具体使用
1)在布局文件中
<org.xwalk.core.XWalkView android:id="@+id/activity_main"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
</org.xwalk.core.XWalkView>
2)在activity
import android.app.Activity;
import android.os.Bundle;

import org.xwalk.core.XWalkView;

public class MyActivity extends Activity {
private XWalkView mXWalkView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mXWalkView = (XWalkView) findViewById(R.id.activity_main);
mXWalkView.load("", null);
}

@Override
protected void onPause() {
super.onPause();
if (mXWalkView != null) {
mXWalkView.pauseTimers();
mXWalkView.onHide();
}
}

@Override
protected void onResume() {
super.onResume();
if (mXWalkView != null) {
mXWalkView.resumeTimers();
mXWalkView.onShow();
}
}

@Override
protected void onDestroy() {
super.onDestroy();
if (mXWalkView != null) {
mXWalkView.onDestroy();
}
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (mXWalkView != null) {
mXWalkView.onActivityResult(requestCode, resultCode, data);
}
}

@Override
protected void onNewIntent(Intent intent) {
if (mXWalkView != null) {
mXWalkView.onNewIntent(intent);
}
}
}

缺点:.so文件太大,导致打包后的apk文件很大(一般20多M)

④ android中怎么防止oom

内存泄露的原因:
1. Handler造成内存泄漏

private Handler handler = new Handler(){
@Override
public void handMessage(Message msg){

}
}
当使用内部类(包括匿名类)来创建Handler时,Handler对象会隐式地持有一个外部类对象(通常是一个Activity)的引用。
而Handler通常会伴随一个耗时的后台线程(例如访问网络或者从网络上拉取图片)一起出现,这个后台线程在任务执行完毕(例如图片下载完成)之后,通过消息机制通知Handler,然后Handler把图片更新到界面上(主线程中)。
当用户在网络请求过程中关闭了Activity,正常情况下,Activity不再被使用,它就有可能在GC检查时被回收掉。但是由于这时线程尚未执行完,而该线程持有Handler的引用,Handler持有Activity的引用,就导致Activity无法被回收(即内存泄露),直到网络请求结束(例如图片下载完成)。
另外,如果你执行了Handler的postDelayed()方法,该方法会将你的Handler装入一个Message,并把这条Message推到MessageQueue中,那么在你设定的delay到达之前,会有一条MessageQueue —> Message —> Handler —> Activity的链,导致你的Activity被持有引用而无法被回收。
使用Handler导致内存泄露的解决办法:
一、通过程序逻辑进行保护
A. 在finish Activity的时候停掉你的后台线程,线程停掉了,就相当于切断了Handler与外部连接的线,Activity自然会在合适的时候被回收。
B. 如果Handler被delay的Message持有了引用,那么使用相应的Handler的removeCallbacks()方法,把消息对象从消息队列中移除即可。
二、将Handler声明为静态类
静态类不持有外部类的引用对象,所以Activity可以随意被回收。
static class MyHandler extends Handler{

@Override
public void handleMessage(Message msg){
}
}
此时由于Handler不再持有外部类对象的引用,导致程序不允许你在Handler中操作Activity中的对象。所以你需要在Handler中增加一个对Activity的弱引用(WeakReference)
static class MyHandler extends Handler{
WeakReference<Activity> activityReference;
public MyHandler(Activity activity){
activityReference = new WeakReference<Activity>(activity);
}

@Override
public void handleMessage(Message msg){
final Activity activity = activityReference.get();
}
}
对应以上的代码,用户在关闭Activity之后,就算后台线程还没结束,但由于仅有一条来自Handler的弱引用指向Activity,所以GC仍然会在检查的时候把Activity回收掉。
So, 关于Handler内存泄露的问题就不会出现。

⑤ android怎么防止内存溢出

Android的内存主要表现在:
1. 在Android平台上,长期保持一些资源的引用,造成一些内存不能释放,带来的内存泄露问题很多。比如:Context(下文中提到的Activity都是Context),在一些你需要保持你的首个类对象状态,并且把状态传入其他类对象中时,这样消除掉首个类对象之前,你必须先把接收类对象释放掉。需要注意一点的是:因为在Java或者Android内存机制中,顶点的结点释放前必须保证其他对象没有调用才能被系统GC回收释放。我们来看一段代码:
@Override
protected void onCreate(Bundlestate) {
super.onCreate(state);
TextViewlabel = new TextView(this);
label.setText("Leaksare bad");
setContentView(label);
}
这个代码的意思就是我们把一个TextView的实例加载到了我们正在运行的Activity(Context)当中,因此,通过GC回收机制,我们知道,要释放Context,就必须先释放掉引用他的一些对象。如果没有,那在要释放Context的时候,你会发现会有大量的内存溢出。所以在你不小心的情况下内存溢出是一件非常容易的事情。保存一些对象时,同时也会造成内存泄露。最简单的比如说位图(Bitmap),比如说:在屏幕旋转时,会破坏当前保持的一个Activity状态,并且重新申请生成新的Activity,直到新的Activity状态被保存。我们再看一段代码:
privatestatic DrawablesBackground;
@Override
protected void onCreate(Bundlestate) {
super.onCreate(state);
TextView label = newTextView(this);
label.setText("Leaks arebad");
if (sBackground == null){
sBackground =getDrawable(R.drawable.large_bitmap);
}
label.setBackgroundDrawable(sBackground);
setContentView(label);
}
这个代码是非常快的同时也是错误的。它的内存泄露很容易出在屏幕转移的方向上。虽然我们会发现没有显示的保存Context这个实例,但是当我们把绘制的图连接到一个视图的时候,Drawable就会将被View设置为回调,这就说明,在上述的代码中,其实在绘制TextView到活动中的时候,我们已经引用到了这个Activity。链接情况可以表现为:Drawable->TextView->Context。
所以在想要释放Context的时候,其实还是保存在内存中,并没有得到释放。
如何避免这种情况:主要在于。线程最容易出错。大家不要小看线程,在Android里面线程最容易造成内存泄露。线程产生内存泄露的主要原因在于线程生命周期的不可控。下面有一段代码:
publicclass MyTest extendsActivity {
@Override
publicvoid onCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new MyThread().start();
}
privateclass MyThread extends Thread{
@Override
public void run() {
super.run();
//do somthing
}
}
}
代码很简单,但是在Android上又来新问题了,当我们在切换视图屏幕的时候(横竖屏),就会重新建立横屏或者竖屏的Activity。我们形象的认为之前建立的Activity会被回收,但是事实如何呢?Java机制不会给你同样的感受,在我们释放Activity之前,因为run函数没有结束,这样MyThread并没有销毁,因此引用它的Activity(Mytest)也有没有被销毁,因此也带来的内存泄露问题。
有些人喜欢用Android提供的AsyncTask,但事实上AsyncTask的问题更加严重,Thread只有在run函数不结束时才出现这种内存泄露问题,然而AsyncTask内部的实现机制是运用了ThreadPoolExcutor,该类产生的Thread对象的生命周期是不确定的,是应用程序无法控制的,因此如果AsyncTask作为Activity的内部类,就更容易出现内存泄露的问题。
线程问题的改进方式主要有:
l 将线程的内部类,改为静态内部类。
l 在程序中尽量采用弱引用保存Context。
2. 万恶的bitmap。。。
Bitmap是一个很万恶的对象,对于一个内存对象,如果该对象所占内存过大,在超出了系统的内存限制时候,内存泄露问题就很明显了。。
解决bitmap主要是要解决在内存尽量不保存它或者使得采样率变小。在很多场合下,因为我们的图片像素很高,而对于手机屏幕尺寸来说我们并不用那么高像素比例的图片来加载时,我们就可以先把图片的采样率降低在做原来的UI操作。
如果在我们不需要保存bitmap对象的引用时候,我们还可以用软引用来做替换。具体的实例代码google上面也有很多。
综上所述,要避免内存泄露,主要要遵循以下几点:
第一:不要为Context长期保存引用(要引用Context就要使得引用对象和它本身的生命周期保持一致)。
第二:如果要使用到Context,尽量使用ApplicationContext去代替Context,因为ApplicationContext的生命周期较长,引用情况下不会造成内存泄露问题
第三:在你不控制对象的生命周期的情况下避免在你的Activity中使用static变量。尽量使用WeakReference去代替一个static。
第四:垃圾回收器并不保证能准确回收内存,这样在使用自己需要的内容时,主要生命周期和及时释放掉不需要的对象。尽量在Activity的生命周期结束时,在onDestroy中把我们做引用的其他对象做释放,比如:cursor.close()。
其实我们可以在很多方面使用更少的代码去完成程序。比如:我们可以多的使用9patch图片等。有很多细节地方都可以值得我们去发现、挖掘更多的内存问题。我们要是能做到C/C++对于程序的“谁创建,谁释放”原则,那我们对于内存的把握,并不比Java或Android本身的GC机制差,而且更好的控制内存,能使我们的手机运行得更流畅。

转载

⑥ android 怎么样解决webview内存泄露

android webview 加载html都会导致内存溢出
1、使用crosswalk
具体使用
1)在布局文件中

<org.xwalk.core.XWalkView android:id="@+id/activity_main"
xmlns:android=""
android:layout_width="fill_parent"
android:layout_height="fill_parent">
</org.xwalk.core.XWalkView>

2)在activity

import android.app.Activity;
import android.os.Bundle;

import org.xwalk.core.XWalkView;

public class MyActivity extends Activity {
private XWalkView mXWalkView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mXWalkView = (XWalkView) findViewById(R.id.activity_main);
mXWalkView.load("", null);
}

@Override
protected void onPause() {
super.onPause();
if (mXWalkView != null) {
mXWalkView.pauseTimers();
mXWalkView.onHide();
}
}

@Override
protected void onResume() {
super.onResume();
if (mXWalkView != null) {
mXWalkView.resumeTimers();
mXWalkView.onShow();
}
}

@Override
protected void onDestroy() {
super.onDestroy();
if (mXWalkView != null) {
mXWalkView.onDestroy();
}
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (mXWalkView != null) {
mXWalkView.onActivityResult(requestCode, resultCode, data);
}
}

@Override
protected void onNewIntent(Intent intent) {
if (mXWalkView != null) {
mXWalkView.onNewIntent(intent);
}
}
}

缺点:.so文件太大,导致打包后的apk文件很大(一般20多M)

⑦ android中用getApplicationContext会不会避免某些内存泄漏问题

Android上 ,Context可以用于很多操作,但是大部分时候是用来加载以及使用资源。这就是为什么所有的widgets在他们的构造函数中接受一个Context参数。在一般的android应用中,通常有两种Context:分别是Activity和Application。通常的,当咱们的类和方法需要使用到context时,咱们传递的是Activity这个context:

@Override
protected void onCreate(Bundle state)
{
super.onCreate(state);
TextView label = new TextView(this);
label.setText("Leaks are bad");
setContentView(label);
}

这意味着views拥有一个对整个activity的引用,也就是引用了activity所拥有的一切;通常的,这指的是完整的视图层级结构以及所有它的资源。因此,如果泄露了一个Context(“泄漏”意味着保持着它的一个引用,从而使它不能被垃圾回收机制回收),就意味着泄漏了很多的内存。如果不小心, 泄漏一个activity的所有资源真的非常容易。
当屏幕的方向发生改变的时候,系统默认将会销毁当前的activity并且创建一个新的activity同时保持着原有的状态。在做这个的时候,Android会从资源重新加载应用的UI。现在,想象一下自己写了一个应用,这个应用有一张很大的bitmap。不想再每一次旋转的时候重新加载它。最简单的方法让bitmap持续作用而不随每一个方向而重新加载 ,就是把它放进一个静态域:

private static Drawable sBackground;
@Override
protected void onCreate(Bundle state)
{
super.onCreate(state);

TextView label = new TextView(this);

label.setText("Leaks are bad");

if (sBackground == null)
{
sBackground = getDrawable(R.drawable.large_bitmap);
}

label.setBackgroundDrawable(sBackground);

setContentView(label);
}

这段代码很快,但是错误也很严重:它泄漏了第一个activity,这个在第一次屏幕改变时被创建的activity。当一个Drawable被关联到一个view上,这个view就相当于在drawable上设置的一个回调。在上面的代码片段中,这表示drawable有一个TextView的引用,而这个TextView又拥有一个activity的引用(Context),activity依次引用了几乎所有的东西(取决于自己的代码)。
这个例子展示了一个最简单的Context 泄漏的情况,可以在Home screen 的源码中看到咱们是如何解决这个问题的( 查找unbindDrawables() 方法) ,这就是当activity 被销毁的时候将drawables 的回调设为null 。有趣的是,可能创造出一系列context泄漏的情况有很多,这非常糟糕。他们会是很快内存溢出。
有两种简单的方法来避免context 相关的内存泄漏。最显着地一个是避免context 逃出他自己的范围之外。上面的例子就展示了使用静态引用的情况,而内部类和他们对外部类的的隐式引用也是同样危险的。第二种方法是使用Application context 。这个context 的生存周期和应用的生存周期一样长,而不是取决于activity 的生存周期。如果想保持一个长期生存的对象,并且这个对象需要一个context ,记得使用application 对象。可以通过调用Context.getApplicationContext() or Activity.getApplication() 来获得。
总而言之,想要避免context 相关的内存泄漏 ,记住以下几点:
A:不要对activity 的context 长期引用( 一个activity 的引用的生存周期应该和activity 的生命周期相同)
B:试着使用关于application的 context 来替代和activity相关的context
C:如果一个acitivity 的非静态内部类的生命周期不受控制,那么避免使用它;使用一个静态的内部类并且对其中的activity 使用一个弱引用。解决这个问题的方法是使用一个静态的内部类,并且对它的外部类有一WeakReference,就像在ViewRoot中内部类W所做的就是这么个例子。
D:垃圾回收器不能处理内存泄漏的保障。

⑧ Android中什么情况下会导致内存泄露

集合类泄漏
集合类如果仅仅有添加元素的方法,而没有相应的删除机制,导致内存被占用。如果这个集合类是全局性的变量 (比如类中的静态属性,全局性的 map 等即有静态引用或 final 一直指向它),那么没有相应的删除机制,很可能导致集合所占用的内存只增不减。比如上面的典型例子就是其中一种情况,当然实际上我们在项目中肯定不会写这么 2B 的代码,但稍不注意还是很容易出现这种情况,比如我们都喜欢通过 HashMap 做一些缓存之类的事,这种情况就要多留一些心眼。
单例造成的内存泄漏
由于单例的静态特性使得其生命周期跟应用的生命周期一样长,所以如果使用不恰当的话,很容易造成内存泄漏
匿名内部类/非静态内部类和异步线程
非静态内部类创建静态实例造成的内存泄漏
有的时候我们可能会在启动频繁的Activity中,为了避免重复创建相同的数据资源
Handler 造成的内存泄漏
Handler 的使用造成的内存泄漏问题应该说是最为常见了,很多时候我们为了避免 ANR 而不在主线程进行耗时操作,在处理网络任务或者封装一些请求回调等api都借助Handler来处理,但 Handler 不是万能的,对于 Handler 的使用代码编写一不规范即有可能造成内存泄漏。另外,我们知道 Handler、Message 和 MessageQueue 都是相互关联在一起的,万一 Handler 发送的 Message 尚未被处理,则该 Message 及发送它的 Handler 对象将被线程 MessageQueue 一直持有。
由于 Handler 属于 TLS(Thread Local Storage) 变量, 生命周期和 Activity 是不一致的。因此这种实现方式一般很难保证跟 View 或者 Activity 的生命周期保持一致,故很容易导致无法正确释放。

⑨ android开发内存优化之如何有效避免oom

  1. 减小对象的内存占用

  2. 内存对象的重复利用

  3. 避免对象的内存泄露

  4. 内存使用策略优化

阅读全文

与android避免内存泄露相关的资料

热点内容
滴滴金融app被下架如何还款 浏览:208
jpg转换成pdf免费软件 浏览:741
范里安pdf 浏览:443
伪造pdf 浏览:75
能删除android文件夹吗 浏览:446
LINUX使用V2ray 浏览:797
找人帮忙注册app推广是什么 浏览:820
独立服务器如何恢复初始化 浏览:11
优秀到不能被忽视pdf 浏览:316
导游程序员家政 浏览:586
22乘28的快速算法 浏览:337
软通动力程序员节2021 浏览:845
安卓系统如何卸载安装包 浏览:870
短信删除助手文件夹 浏览:688
java办公自动化 浏览:342
php中超链接 浏览:254
linux默认路由设置 浏览:36
linux如何挂载iso 浏览:432
vs程序换文件夹后不能编译 浏览:558
安卓源码编译输入脚本没反应 浏览:47