Android 内存剖析 – 发现潜在问题------比较好android博客
转载地址:http://www.importnew.com/8246.html
简介
移动平台上的开发和内存管理紧密相关。尽管随着科技的进步,现今移动设备上的内存大小已经达到了低端桌面设备的水平,但是现今开发的应用程序对内存的需求也在同步增长。主要问题出在设备的屏幕尺寸上-分辨率越高需要的内存越多。熟悉Android平台的开发人员一般都知道垃圾回收器并不能彻底杜绝内存泄露问题,对于大型应用而言,内存泄露对性能产生的影响是难以估量的,因此开发人员必须要有内存分析的能力。本文介绍一些有用的工具,以及如何使用它们来检测这些关键的内存泄露问题。
工具
有很多工具可以用来帮助检测内存泄露问题,这里列举了一些,并附上一点相应的介绍:
工具名称: |
简介: |
DDMS (Dalvik调试监视服务器) |
和Android一起推出的调试工具(android sdk的tools目录下就有)。提供端口转发服务、截屏、线程监控、堆dump、logcat、进程和无线状态监控以及一些其他功能。可以通过”./ddms”命令启动该工具,同时它也被集成在ADT中,安装以后Eclipse切到DDMS视图即可。 |
MAT (内存分析工具) |
快速的Java堆分析器,该工具可以检测到内存泄露,降低内存消耗,它有着非常强大的解析堆内存空间dump能力。还有很多其他功能无法在这里一一列出,可以安装一下MAT的eclipse插件试试,要活的更多详细信息请点击这里。 |
术语介绍
内存分析涉及到很多专用术语,他们在本文中将频繁出现,这里给出每个术语的定义:
术语: |
定义: |
堆大小 |
分配给Java堆的内存,在Android平台,这些内存都是针对每个Activity分配的(这还取决于设备) |
堆转储文件 |
一个包含了堆中信息的二进制文件 |
支配树(Dominator Tree) |
一个用来图形化展示对象之间关系的工具,详情请参考wiki |
内存泄露 |
内存泄露是指有个引用指向一个不再被使用的对象,导致该对象不会被垃圾回收器回收。如果这个对象有个引用指向一个包括很多其他对象的集合,就会导致这些对象都不会被垃圾回收。因此,需要牢记,垃圾回收无法杜绝内存泄露。 |
GC根 |
GC根是指那些假设可达的对象。 通常包括所有当前栈和系统的类加载器加载的类中引用的对象。(【译者注】栈里引用的对象是指当前执行的方法里的局部变量指向的对象,系统加载器加载的类引用的对象包括类的静态属性引用的对象) |
内存泄露
内存泄露是指有个引用指向一个不再被使用的对象,导致该对象不会被垃圾回收器回收。如果这个对象有个引用指向一个包括很多其他对象的集合,就会导致这些对象都不会被垃圾回收。
图. 1
被一个对象直接消耗的内存
例子:
public final class myObject { // 头部: 8字节
private int valueA; // 整型: 4字节
private int valueB; // 整型: 4字节
private char valueC[]; // 字符型数组: 4字节
}
一个myObject对象共消耗20个字节保留堆(Retained Heap)
因释放了某个对象后,可以释放的所有内存总和。
GC前:GC即将回收对象A
图. 2
GC后:回收对象A(300字节)从而导致回收对象B(50字节)和C(50字节),同时释放了对象B以后对象D也会被回收(100字节),因此回收对象A就可以释放500字节的内存,所谓保留队正式这些对象直接占用的浅堆总和。
图 3
检测内存泄露
Logcat输出的log
第一种发现内存泄露的方法是检查logcat输出的log。当垃圾回收器工作时,可以在Logcat中看到它的消息,这消息长的样子类似于:
D/dalvikm( 14302): GC_CONCURRENT freed 2349K, 65% free 3246K/9551K, external 4703K/5261K, paused 2ms+2ms
这条消息的第一个部分说明该消息产生的原因,一共有四种类型:
GC_CONCURRENT |
当堆变得很大,防止出现堆溢出异常时产生 |
GC_FOR_MALLOC |
如果GC_CONCURENT类型的操作没有及时运行,并且应用程序还需要分配更多内存时产生。 |
GC_EXTERNAL_ALLOC |
在Android3.0 (Honeycomb)以前,释放通过外部内存(externel memory, 通过JNI代码中malloc分配得到的内存)时产生。Android3.0和更高版本中不再有这种类型的内存分配了。 |
GC_EXPLICIT |
调用System.gc时产生 |
“freed 2349K,” – 说明释放了多少内存.
“65% free 3246K/9551K” – 65%表示目前可分配内存占比例,3426K表示当前活动对象所占内存,9551K表示堆大小。
“external 4703K/5261K” – indicates external memory allocation, how much external memory the app has allocated and the soft limit of allocation.说明外部内存的分配,已经分配了多少以及能够分配的上限。
“paused 2ms+2ms” –说明GC运行完成需要的时间。
有了这些信息,我们就可以知道GC运行几次以后有没有成功释放出一些内存,如果分配出去的内存在这几个周期中持续增加,那么很明显存在内存泄露。下面的例子中就是存在内存泄漏时的Log。(【译者注】图片有点不清楚,但是大概可以看出来GC运行了好多次,可分配内存比例反而从47%降到45%了)
图. 4
OutOfMemoryError 异常
跟踪内存分配情况
成功的发现内存泄露问题以后,就应该查找根源在哪里了,有两个工具可以用来辅助分析问题根源所在。
DDMS
DDMS是一个强大的工具,他可以提供有很价值的信息,它还可以生成一个HPROF dump文件,该文件可以使用MAT打开分析。在Eclipse中打开DDMS,只需安装ADT插件以后打开DDMS视图即可。
图. 5
图. 6
图. 7
内存分析工具 (MAT)
MAT是个强大的内存分析工具,可以单独使用也可以作为Eclipse的插件(【译者注】这个工具不在ADT中,可以在http://www.eclipse.org/mat/downloads.php下载,有stand-alone版本和Eclipse安装的update URL),这两种使用方法唯一的区别就是如何打开一个HPROF文件。独立版本需要一个打包好的HPROF文件。我们可以使用android adk自带的hprof-conv工具(在android sdk的tools目录下)打包。如果使用Eclipse插件版的MAT则不需要,直接在Eclipse中打开MAT视图即可。
概述
当打开HPROF文件后,可以看到一个Overview界面,它由以下元素构成:
- Overview标签页,提供一个概览界面。
- Histogram视图,它提供每个类的对象统计(本文稍后详述)
- 支配树(Dominator Tree),提供程序中最占内存的对象 (described later in the article).
- 对象查询语言(Object Query Language Studio), 用来写MAT查询的工具.
- 专家系统测试(Expert System Test) –
- 堆Dump概况(Heap Dump Overview) –提供堆dump文件的详细信息
- 疑似泄露点(Leak Suspects) – 提供内存泄露疑点占用内存大小,被谁加载的,以及类型等详细信息。
- Top Components – 提供占内存最多的对象信息,还包括可能的内存浪费信息.
- 查询浏览器(Query Browser) – 提供很多很有用的查询,有助于内存分析,本文将会介绍最有用的那些查询。根据地址查找对象 – 可以根据提供的一个地址查找某个特定的对象.
- 对象列表(List Objects) – 显示应用中所有对象,以及这些对象持有哪些其他对象和被哪些其他对象持有,(MAT会提示查询哪一个对象)。
- 根据类显示对象(Show Objects by Class) – 列出每个类有多少对象.
- 到GC根节点的路径(Path to GC Roots) – 显示到根节点的引用路径 (有好多过滤选项).
- 合并到GC根节点的最短路径(Merge Shortest Paths to GC Roots) –找到从GC根节点到一个对象或一组对象的共同路径。
- 即时支配(Immediate Dominators) – Finds and aggregates on a class level all objects dominating a given set of objects. 在给定的一组对象中,从类的层面上查找并聚合所有支配关系。(【译者注】好吧,我觉得实在有必要说一下支配的意思,支配在计算机的控制流理论中意思是假如说从起始节点到节点B的所有路径都经过节点A,则节点A支配节点B。在垃圾回收理论中应该是指从某个对象在另外一个对象的保留堆中)
- 显示保留集合(Show Retained Set) – 计算一个对象的保留堆大小.
- 饼图 – 显示持有内存最大的对象
- 直方图 – 显示每个类的对象数量
- 支配树 – 列出所有对象,并按照对象持有的保留堆大小排序
- 检查器 – 选择一个对象,并显示其详细信息
图. 8
直方图(Histogram)
MAT最有用的工具之一,它可以列出任意一个类的实例数。查找内存泄露或者其他内存方面问题是,首先看看最有可能出问题的类,这个类有多少个实例是个比较好的选择。它支持使用正则表达式来查找某个特定的类,还可以计算出该类所有对象的保留堆最小值或者精确值。
- 计算保留堆大小
a) 计算保留堆最小值(Calculate Minimum Retained Size) –计算保留堆最小值,并显示在表格中.
b) 计算保留堆精确值(Calculate Precise Retained Size) – 计算保留堆精确值(这个过程需要一点时间) 并且显示在表格中. - 正则表达式(Regex pattern) – 让用户查询某个特定的对象类
图. 9
另外,当选择了某条显示条目后,可以通过右击弹出菜单。在诊断内存相关问题时,这个菜单是个非常重要的工具。如果开发者怀疑这里有个内存泄露,可以通过菜单直接查看该类的对象持有哪些其他对象,当然,MAT支持过滤查询结果(比如说限制被持有对象的类型)。查询结果出来时,列表通过另外一个有用的工具-”Path toGC Roots”-展示给开发人员。它支持多种过滤选项,比如说排除弱引用-这是最常见的一个选项,因为当GC运行时,被弱引用持有的对象会被GC直接回收,所以这种对象是不会造成内存泄露的,一般直接把这种信息排除。如果MAT预定义的查询不能满足用户需求的话,它还支持自己定制查询,定制的自由度非常大,拥有无限的可能。本文稍后会介绍如何高效的定制查询。
图. 10
图 11
支配树(Dominator Tree)
支配树可以算是MAT中第二有用的工具,它可以将所有对象按照保留堆大小排序显示。用户可以直接在“Overview”选项页中点击“Dominator Tree”进入该工具,也可以在上面提到的菜单中选择“immediate dominators”进入该工具。前者显示dump文件中所有的对象,后者会从类的层面上查找并聚合所有支配关系。支配树有以下重要属性:
- 属于X的子树的对象表示X的保留对象集合。
- 如果X是Y的持有者,那么X的持有者也是Y的持有者。
- 在支配树中表示持有关系的边并不是和代码中对象之间的关系直接对应,比如代码中X持有Y,Y持有Z,在支配树中,X的子树中会有Z。
这三个属性对于理解支配树而言非常重要,一个熟练的开发人员可以通过这个工具快速的找出持有对象中哪些是不需要的以及每个对象的保留堆。
图. 12
查询(Queries)
查询是用来检查对象树的基本工具,内存分析就是在许多对象中查找不希望看到的引用关系的过程-这件事听上去容易做起来难。如果可以过滤这些对象和应用关系的话可以使这项复杂的运动简单不少。一个开发人员想要成功的调试内存问题,必须掌握两个关键点。第一个是对自己的应用充分了解,如果对自己应用程序中的对象之间的关系不够了解的话,是不能找到内存问题的。第二个是掌握过滤和查找的技巧。如果开发者知道对象结构,而且也可以快速的找到想要的东西,那么找到那些异常状况将会变得容易一些。这里列出MAT工具所有内建的查询:
(【译者注】下面表格中的前两列都是MAT工具中菜单的名称)
查询: |
选项: |
描述: |
List objects |
With Outgoing References |
显示选中对象持有哪些对象. |
With Incoming References |
显示选中对象被哪些对象持有。[如果一个类有很多不需要的实例,那么可以找到哪些对象持有该对象,让这个对象没法被回收] |
|
Show object by class |
With Outgoing References |
显示选中对象持有哪些对象, 这些对象按类合并在一起排序 |
With Incoming References |
显示选中对象被哪些对象持有.这些对象按类合并在一起排序 |
|
Path to GC Roots |
With all references |
显示选中对象到GC根节点的引用路径,包括所有类型引用. |
Exclude weak references |
显示选中对象到GC根节点的引用路径,排除了弱引用. [弱引用不会影响GC回收对象] |
|
Exclude soft references |
显示选中对象到GC根节点的引用路径,排除软引用(【译者注】软引用持有的对象在内存空间足够时,GC不回收,内存空间足够时,GC回收) |
|
Exclude phantom references |
显示选中对象到GC根节点的引用路径,排除虚引用(【译者注】虚引用是最弱的引用,get()总是返回null,当它的对象被GC回收时,GC将reference放在ReferenceQueue中,用户代码当发现这个reference在在ReferenceQueue时就知道它持有的对象已经被回收了,这时可以做一些清理工作。《Java编程思想》第四版,中文版,第87页写到Java的finilize方法是为了对象被回收前做清理工作,但是事实上会有隐患,虚引用正是弥补) |
|
Merge Shortest Paths to GC Roots. |
选项和“Path to GC Roots”一样 |
显示GC根节点到选中对象的引用路径 |
Java Basics |
References Statistics Class Loader Explorer |
显示引用和对象的统计信息,列出类加载器,包括定义的类 |
Customized Retained Set |
计算选中对象的保留堆,排除指定的引用 |
|
Open in Dominator Tree |
对选中对象生成支配树 |
|
Show as Histogram |
展示任意对象的直方图 |
|
Thread Details |
显示线程的详细信息和属性 |
|
Thread Overview and Stacks |
- |
|
Java Collections |
Array Fill Ratio |
输出数组中,非基本类型、非null对象个数占数组总长度的比例。 |
Arrays Grouped by Size |
显示数组的直方图,按大小分组 |
|
Collection Fill Ratio |
输出给定集合中,非基本类型、非null对象个数占集合容量的比例。 |
|
Collections Grouped by Size |
显示集合的直方图,按大小分组 |
|
Extract Hash Set Values |
列出指定hash集合中的元素 |
|
Extract List Values |
列出指定LinkedList,ArrayList或Vector中的元素 |
|
Hash Entries |
展开显示指定HashMap或Hashtable中的键值对 |
|
Map Collision Ratio |
输出指定的映射集合的碰撞率 |
|
Primitive Arrays With a Constant Value |
列出基本数据类型的数组,这些数组是由一个常数填充的。 |
|
Leak Identification |
Component Report Top Consumers |
分析可能的内存浪费或者低效使用的组件,并输出最大的那个 |
报告(Reports)
MAT自带有一个报告生成系统,他可以自动分析dump文件并且生成报告给用户。第一种报告叫做“泄露疑点(Leak suspects)”,MAT分析dump文件,检查是否存在一些个头大的对象被一些引用持有保持活动状态,需要注意的是,泄露疑点并不一定是真的内存泄露。第二种报告叫做“顶级组件(Top Components)“,它包括可能的内存浪费信息,占用内存大的对象以及引用的统计信息。此报告对内存优化有很大帮助。
泄露疑点报告
泄露疑点报告包括一些潜在的内存泄露信息,再次强调一下,在这里列出的对象并不一定是真正的内存泄露,但它仍然是检查内存泄露的一个绝佳起点。报告主要包括描述和到达聚点的最短路径, 第三部分(每种类型积累的对象)主要是从第二部分衍生出来的(根据类型排序)。
图 13
“到聚点的最短路径” 非常有用,它可以让开发人员快速发现到底是哪里让这些对象无法被GC回收。
图. 14
顶级组件报告
这种报告包含很多有用的信息,特别是对那些想要降低内存使用的人来说。它包括涉嫌内存浪费的的对象,还包括引用的统计信息。整个报告非常简单直白,因此这里不需要过多的详细介绍了。
图. 15
使用MAT检测内存泄露
本小节主要介绍如何使用MAT检测内存泄露的实践部分,因此将会提供一段会造成内存泄露的代码作为例子。
会内存泄露的样例代码
第一个内存泄露例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
public class MainActivity extends Activity {
//静态属性持有非静态内部类的实例--这么做非常糟糕
static MyLeakedClass leakInstance = null ;
@Override
public void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
// Static field initialization
if (leakInstance == null )
leakInstance = new MyLeakedClass();
ImageView mView = new ImageView( this );
mView.setBackgroundResource(R.drawable.leak_background);
setContentView(mView);
}
/*
*非静态内部类
*/
class MyLeakedClass {
int someInt;
}
}
|
图. 17
从第一次旋转开始,每次都存在3mb的差异。每次旋转后,堆的大小都涨3mb。这是有什么东西不对劲的第一个警告,然后LogCat没有显示任何释放已分配内存的信号。这时就需要检查应用程序内部内存的情况了,运行DDMS,获取HPROF文件,然后用自带的MAT打开。
主屏幕上的确显示了有什么东西导致内存泄露了-它大概长的和图18差不多。
图. 18
饼图上显示,有很大一部分内存被资源文件占用-这很正常,因为任何应用都有一个GUI,但是本例子只有一个资源文件,因此问题应该应该隐藏在这里。还有两个FrameLayout实例(每个有3mb)需要检查,开发者还可以沿着一些路径还检查内存泄露问题。
基于直方图的检查
图. 19
有三个比较大的bitmap对象,这么看来这个本例最坏可能有两到三个内存泄露。这几个对象的内存大小符合LogCat的输出,让我们在检查一下他们到GC根节点的路径(剔除所有弱应用)。第一个bitmap对象看上去没什么问题,因为它只有一个应用指向自己,没有被任何其他对象引用,而且它正在等着被垃圾回收器回收。
图. 20
图 21
看来问题就出在剩下的第三个bitmap上了。它到GC根节点只有一条路径,而且它是被“leakInstance”对象持有的,正是leakInstance对象阻止了该bitmap对象被回收。
图. 22
同时,在路径上还有一个MainActivity对象 – 看到MainActivity对象不奇怪,因为每次旋转都会新创建一个Activity,让我们看看到底发生了什么。首先通过正则表达式过滤器在直方图中找出MainActivity对象。
图. 23
图. 24
第一个MainActivity对象有一个引用指向context和ActivityThread,因此它看上去是现在正在显示的Activity。
图. 25
第二个对象只有一个引用指向自己,它正等着被垃圾回收,到目前为止,一切看上去都正常的。
图 26
现在再看第三个 – 就是它了!有个强引用指向leakInstance对象,就是它阻止了该对象被垃圾回收。
图. 27
基于支配树的检查
开发者可以通过很多种方法找到内存泄露。本文只能介绍其中几种,第二个要介绍的是基于支配树视图的。打开HPROF文件的支配树视图,按照保留堆大小进行排序。正如预料的一样,最上面的是资源类对象,还有三个FrameLayout类的对象(每个3mb)以及一个Bitmap对象(1mb)。FrameLayout对象看上去嫌疑很大,因此我们首先检查它们。因为支配树已经列出了具体的对象,因此我们可以直接查看它们到GC根节点的路径。
图. 28
第一个对象就是问题所在!它到GC根节点的唯一路径正是leakInstance对象,因此它是一个泄露。
图. 29
第二个和第三个对象分别是当前正在显示和正在等着垃圾回收的。
图. 30
让我们在看看那个bitmap对象,它也有可能是一个内存泄露。选择android.graphic.Bitmap,选择显示到GC根节点的路径,剔除所有弱引用。
图. 31
bitmap类型有三个对象,每个对象到GC根节点的路径都可以查看到,上面说的情况再次重演,三个实例中的两个很显然没问题,但是第三个对象指向leakInstance,它一直都是活动状态,不会被回收。
图. 32
可能还有上百条路径可以顺藤摸瓜找出最终的泄露点,应该选择哪条路径取决于不同的开发者了,不同的开发人员有对如何分析内存有着不同的见解。
第二个内存泄露例子
第二个内存泄露场景发生在application context上。它将application context传递给一个单例模式的类,并将其作为一个属性保留下来。这个操作将会使得MainActivity无法被垃圾回收。将context作为静态属性保存也会导致同样的结果,因此这种做法应该避免。为了避免重复罗嗦,这里只介绍一种查找内存泄露的方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
public class MainActivity2 extends Activity {
SingletonClass mSingletonClass = null ;
@Override
public void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
mSingletonClass = SingletonClass.getInstance( this );
}
}
class SingletonClass {
private Context mContext = null ;
private static SingletonClass mInstance;
private SingletonClass(Context context) {
mContext = context;
}
public static SingletonClass getInstance(Context context) {
if (mInstance == null ) {
mInstance = new SingletonClass(context);
}
return mInstance;
}
}
|
图. 33
概览界面并没有提供什么重要信息,因此开发人员需要继续自己的探索。这个例子中没有bitmap和其他资源,但是直方图显示这里有很多MainActivity对象 – 检查检查它们也许能得到更多更有价值的消息。
图. 34
将手机旋转3次,直方图显示这里有4个MainActivity对象。嗯,是时候检查是不是有哪个对象阻止它们被回收了。要做到这一点,首先列出所有有incomming refrence的对象。只需要展开视图就很容易发现第一个对象就是当前正在显示的Activity(他包含指向ActivityThread的引用)。
图. 35
继续列出其他两个对象的到GC根节点的路径。其中一个只有一个引用指向它自己,另外一个指向mInstance,该引用在SignletonClass中,还有一个应用指向当前显示的Activity(从mSigletonClass)。这正是一个泄露。
图. 36
很明显可以看出context让垃圾回收无法回收该对象。另外还有一个问题 – 每次创建一个Acitivity实例的时候,context都被传递给SingletonClass。这是个严重的问题,因为context引用指向一个不在需要的Activity,从而让这个Activity保持活跃无法被回收。在比较大的项目中,这中情况可能会导致一些意象不到的行为,并且这种问题很难被检查出来。
译文链接: http://www.importnew.com/2433.html
Android 内存剖析 – 发现潜在问题------比较好android博客相关推荐
- 解决Android SDK Manager无法更新下载 - 猪悟能 - 博客园 (cnblogs.com)
新机器安装SDK Manager时一直下载失败,连接dl.google.com失败,连接dl-ssl.google.com失败.多次搜索和尝试后发现一个比较好的解决办法如下: 引自:解决Android ...
- Linux系统内存管理之伙伴系统分析 - 旭东的博客 - 博客园
Linux系统内存管理之伙伴系统分析 - 旭东的博客 - 博客园 Linux系统内存管理之伙伴系统分析 今天去面试,一位面试官提到了内存管理的伙伴系统,当时就懵了,因为根本就没有听说过.晚上回来在实验 ...
- Android资源总结(开发工具/环境搭建/教程/论坛/博客/反编译工具)
Android资源总结(开发工具/环境搭建/教程/论坛/博客/反编译工具) 在Android发展前景相当好的情况下,本人最近搜集了一些关于Android的相关资源,当然包含以前发布的博客内容,进行了一 ...
- 对#Hello,2015征文#+Android 热敏打印机打印二维码(图片)博客的尝试
原博客链接 #Hello,2015征文#+Android 热敏打印机打印二维码 昨天晚上说抽时间来写一篇关于Android 热敏打印机打印二维码和图片的文章,所幸在下班之前把它给写了,和大家分享吧.我 ...
- 人人视频android资源比ios多,尼墨视频Nemo:一款不掉证书的IOS与Android通用的追剧神器 | 闲一鱼博客...
最近苹果证书掉的真是太频繁了,闲鱼也是无力吐槽,其实闲鱼倒是没受到什么影响,早期的完美看视频.酷看.麻花那些都一直能用,毕竟是在官方App Store里下载的,没这个坏毛病,嘎嘎.但是对于那些之前没早 ...
- 乐乐音乐:Android音乐播放器及动感(KTV)歌词相关博客汇总
相关简介 Java Swing PC版本乐乐音乐播放器 乐乐音乐PC播放器单机版本,支持ape,wav,flac,mp3等多种格式,支持动态ksc.hrc.krc歌词文件和支持和显示翻译歌词和音译歌词 ...
- 小内存VPS主机一键快速安装GHost轻博客程序脚本和演示
小内存VPS一般我们都用来做什么?大部分应该都用来上网用途的,毕竟便宜且独立IP,比一般购买VIP账户好很多,而且稳定性高.其实,我们如果需要搭建小个人网站.博客的也可以使用,比如以前笔者有看到32M ...
- android图表控件 坐标,android-charts 基于Java和Android开发的图形图表控件 | 李大仁博客...
王晓龙 April 8th, 2014 at 09:44 | #1 我再github上看到了你写的控件,给了我很大启发,我现在在做K线图一类的图表,正好用到了您开发的这款控件,但是有些地方使用的不太舒 ...
- android c博客园,android上进行c/C 开发测试(转) - 奋进 - 博客园
Android C编程技巧 运行模拟器 emulator -console * 将文件写入到模拟器的userdata.img文件中 adb push *将一个目录拷贝到模拟器中,包括子目录 adb p ...
- android释放acitity内存,Android 内存泄漏分析与解决方法
在分析Android内存泄漏之前,先了解一下JAVA的一些知识 1. JAVA中的对象的创建 使用new指令生成对象时,堆内存将会为此开辟一份空间存放该对象 垃圾回收器回收非存活的对象,并释放对应的内 ...
最新文章
- ATS 4.2.3自定义日志文件格式的方法
- linux 卸载 openssl,请教Linux下Openssl安装的问题。
- 如何禁用 Azure 虚拟机的日期时间同步
- 使用 Source Generator 自动生成 WEB API
- Java常见的几种内存溢出及解决方法
- 计算机与环境科学,计算机在环境科学与工程方向的应用
- 计算机能力挑战赛_蓝桥杯、PAT、CCF CSP、团体程序设计天梯赛、传智杯、计算机能力挑战赛、软考等大学生编程比赛/考试介绍...
- 快速理解孤儿进程和僵尸进程
- [Javascript] Math ceil()、floor()、round()三个函数的区别
- PS2: 这篇文章中的图片绘图工具使用的是Dia (sudo apt-get install dia)。据说yEd也很不错。...
- python所有软件-太牛逼!一款软件几乎可以操作所有的数据库!
- 软件过程之美 : 软件配置管理策略及主流工具实战
- javascript 常用代码大全(4)
- Linux之top命令
- kali工具 -- setoolkit(克隆网站及利用)
- Prolog入门教程(完整版+专家系统案例)
- 第 9 章 Panel(面板)组件
- 2018微信公开课:微信小游戏的精华内容要点分享!
- 网易邮箱大师如何注册邮箱 注册邮箱方法步骤介绍
- android 批量安装apk,如何一键批量安装APP应用apk安装包?
热门文章
- 前端请求数据过多,Promise.all,_.chunk,_.flatten解决方法之一
- 一网打尽“小黄图”!手把手教你造一只AI鉴黄神器(内附代码及数据集)
- ui和ux的区别_UX和UI设计之间有什么区别?
- 纯前端滑块拼图验证组件(多端兼容)
- 如何禁用计算机休眠,电脑如何关闭休眠功能,教你电脑如何关闭休眠功能
- Numpy中take的用法
- 【数据结构与算法】| Map和Set
- 博士申请 | 香港城市大学计算机学院徐伟涛老师组招收人工智能全奖博士生
- C语言基础练习-输入球体半径,计算球体表面积和体积
- android禁用状态栏5.1,Android5.1禁止状态栏下拉(SystemUI StatusBar)