调用 null 对象的实例方法。
访问或修改 null 对象的字段。
如果一个数组为null,试图用属性length获得其长度时。
如果一个数组为null,试图访问或修改其中某个元素时。
在需要抛出一个异常对象,而该对象为 null 时。
2.CalledFromWrongThreadException
在主线程之外的线程中进行了修改主界面UI的操作
解决: 1、Activity.runOnUiThread(Runnable)
2.Handler
sendMessage(Message)
post(Runnable)
3.AsyncTask
execute()
doInBackground()
onPostExecute()
3.Resources$NotFoundException: String resource IDTextView.setText(int)时报此错误
4.ClassNotFoundException 在编译的时候在classpath中找不到对应的类而发生的错误。
1 所需要的支持类库放错了地方,并没有放在类路径(CLASSPATH环境变量)里面。
2 使用了重复的类库,且版本不一致。导致低版本的被优先使用。
3 类名错了,一般是使用Class.forName的时候,手工指定了类名的情况。
4 没有导入纯JAVA驱动包。
5.NoClassDefFoundError发生在编译时对应的类可用,而运行时在Java的classpath路径中,对应的类不可用导致的错误。
6.java.lang.ArithmeticException 异常的运算条件(除以零)
7.java.lang.ArrayIndexOutOfBoundsException 数组下标越界
8.java.lang.IllegalAccessException "没有访问权限",当应用程序要调用一个类,但当前的方法即没有对该类的访问权限便会出现这个异常。
9.ClassCastException 类转换异常
10.NegativeArray Exception 数组负下标异常
11.FileNotFoundException 当java程序试图打开指定路径名表示的文件失败时,抛出此异常。
12.NumberFormatException 字符串转换为数字异常
https://blog.csdn.net/qq_33450379/article/details/53731318
*************************************************************************************************************
OOM程序申请内存过大,虚拟机无法满足我们,然后自杀了。Android系统的APP每个进程或者虚拟机有最大内存限制,一旦超过这个限制系统就会抛出OOM错误。跟手机剩余内存是否充足没有多少关系。
(1)要开发者使用内存更加合理。
(2)屏幕显示内容有限,内存足够即可。
Android的GC会按照特定的算法来回收不使用的资源,但是gc一般回收的是无主的对象内存或者软引用资源。
1.堆溢出
当报错信息java.lang.OutOfMemoryError后面带有java heap space时,说明是java堆溢出。
- 1
由于Heap是用来存放实例的,堆溢出,也就说明了当前的实例对象过多,而且这些对象一直处于存活状态(JVM判断对象是否存活,是通过判断GC Roots和对象之间的是否存在可达路径)。出现这种问题,一般要考虑下列两种情况:
- 内存泄露:
一般出现这种情形,需要判断是否是内存泄露,即一些无用对象一直被引用,导致GC无法有效回收它,这时可以通过一些工具,Optimizeit Profiler,JProbe Profiler,JinSight , Rational 公司的Purify等。查看Heap dump,看看GC roots到对象之间的引用链,定位到泄露的对象。这些对象是可达的,即在有向图中,存在通路可以与其相连;其次,这些对象是无用的,
https://blog.csdn.net/anxpp/article/details/51325838
- 内存溢出:
另一种情形就是内存溢出,也就是这些对象的确是需要存活的,因此也就不存在GC回收异常。一般这种情况,可能是对象过大,或者对象的生命周期过长,需要从业务层面,减少这些对象在运行期的内存消耗。
另外一种情形,也有可能是我们的堆分配的内存过小,可以通过配置堆的参数(-Xmx最大内存与-Xms 最小内存)来设置
2.栈溢出
栈溢出需要建立两个概念,一个就是整个java stack区域的大小,一个就是单个线程中stack的大小。
整个stack区的大小是由jvm的内存容量- heap容量 - 方法区容量 确定的,是一个固定的值。
单个线程中 stack的大小也是固定的,可以通过 -Xss 配置
StackOverflowError,线程请求的栈的深度超过虚拟机允许的最大深度。
每个线程中stack的容量是固定,由于stack是用于存放各个方法的内部变量表的,所以,当大量的方法被调用,而又未及时结束,或者单个方法内部定义了大量局部变量,使单个栈帧很大,这样使得占用的空间超过了单个线程中stack的深度,因此会报这个异常。
OutOfMemoryError 虚拟机扩展栈时无法分配足够的内存空间
一般情况下,当启用一个线程时,就会给这个线程分配一个固定大小的stack,由于整个java stack区的大小是有限的,当我们的线程过多时,就会抛出OutOfMemoryError异常。由此可见,单个线程stack的大小并非越大越好,因为这与我们的线程数息息相关。
3.方法区溢出
方法区是用于存放类的定义Class文件和常量池等,由此可见,当类或者常量池过多时,会造成方法区溢出
当报错信息java.lang.OutOfMemoryError后面带有PremGen space时,说明是方法区溢出。
- 1
当前的一些框架,如Spring、Hibernate等,会使用CGlib技术对类进行增强,相应地会增加类的大小;
还有一些应用,会动态生成JSP文件,JSP文件是需要编译成Class文件的,大量的文件也有溢出的可能;
或者开发代码中往常量池添加过多的常量,也有可能造成常量池溢出。
另外一种可能就是我们的应用本身的类就太多,而方法区设置的容量不足,也会容易溢出。
设置方法区的大小,可通过配置-XX:PremSize 设置最小值,-XX:MaxPremSize设置最大值。
(1) 在退出Activity时,把handler的Message和Runnable给干掉
(2) Activity context引用不当导致退出时,整个Activity无法回收。程序中尽量使用ApplicationContext
(3) 检查添加了Listener接口回调后,没有反注册掉
(4) List,HashMap等集合类,在退出时clear掉,并置为空
(5) 单例类中是否引用了ActivityContext
*********************************************************************************************************
ANR:Application Not Responding,即应用无响应 。ANR产生时, 系统会生成一个traces.txt的文件放在/data/anr/下.
1. 不要让主线程干耗时的工作2. 不要让其他线程阻塞主线程的执行
按键或触摸事件在特定时间内无响应
2:BroadcastTimeout(10 seconds)
BroadcastReceiver 在特定时间内无法处理完成
3:ServiceTimeout(20 seconds)
4:非主线程原因
1.CPU满负荷
这个时候你看到的trace信息可能会包含这样的信息:
Process:com.anly.githubapp
...
CPU usage from 3330ms to 814ms ago:
6% 178/system_server: 3.5% user + 1.4% kernel / faults: 86 minor 20 major
4.6% 2976/com.anly.githubapp: 0.7% user + 3.7% kernel /faults: 52 minor 19 major
0.9% 252/com.android.systemui: 0.9% user + 0% kernel
...
100%TOTAL: 5.9% user + 4.1% kernel + 89% iowait
当是CPU占用100%, 满负荷了.
其中绝大数是被iowait即I/O操作占用了.
此时分析方法调用栈, 一般来说会发现是方法中有频繁的文件读写或是数据库读写操作放在主线程来做了.
2.内存原因
其实内存原因有可能会导致ANR, 例如如果由于内存泄露, App可使用内存所剩无几, 我们点击按钮启动一个大图片作为背景的activity, 就可能会产生ANR, 这时trace信息可能是这样的:
// 以下trace信息来自网络, 用来做个示例
Cmdline: android.process.acore
DALVIK THREADS:
"main"prio=5 tid=3 VMWAIT
|group="main" sCount=1 dsCount=0 s=N obj=0x40026240self=0xbda8
| sysTid=1815 nice=0 sched=0/0 cgrp=unknownhandle=-1344001376
atdalvik.system.VMRuntime.trackExternalAllocation(NativeMethod)
atandroid.graphics.Bitmap.nativeCreate(Native Method)
atandroid.graphics.Bitmap.createBitmap(Bitmap.java:468)
atandroid.view.View.buildDrawingCache(View.java:6324)
atandroid.view.View.getDrawingCache(View.java:6178)
...
MEMINFO in pid 1360 [android.process.acore] **
native dalvik other total
size: 17036 23111 N/A 40147
allocated: 16484 20675 N/A 37159
free: 296 2436 N/A 2732
可以看到free的内存已所剩无几.当然这种情况可能更多的是会产生OOM的异常...
哪些地方是执行在主线程的
- Activity的所有生命周期回调都是执行在主线程的.
- Service默认是执行在主线程的.
- BroadcastReceiver的onReceive回调是执行在主线程的.
- 没有使用子线程的looper的Handler的handleMessage, post(Runnable)是执行在主线程的.
- AsyncTask的回调中除了doInBackground, 其他都是执行在主线程的.
- View的post(Runnable)是执行在主线程的.
1. 启Thread方式(继承Thread、实现Runnable接口)
2.使用AsyncTask
3.IntentService
https://blog.csdn.net/a332324956/article/details/77800315