异常分析 (空间太小)

  1. 出现 异常的原因:
  2. 碎片化 。
  3. MobileAPI脏数据
  4. 混淆时没有Keep 要使用的类或者方法  。 
 
  本地开发要与线上分开  
 异常信息中提示  “方法名”unknown source 内容 ,会加大我们准确定位的crash的难度 。
 导致unknown source 的原因
    1.执行javac时丢失文件名和行号 
       我们要在javac编译时保留debug信息  <javac  debug="true" debuglevel="source ,line" ....>
   2. 执行了代码混淆丢失文件名个行号
       在proguard文件中增加 -keeparttributes  SourceFile,LineNumberTable
 
 
 
 
名称  关键字  发生频率 发生原因 解决方式
名称  关键字 发生频率 发生场景 解决方式
 空指针 NullPointException   1.调用接口时,过于信息返回数据 ,一旦为空的Json,引发崩溃
2.在使用asyncTask调用接口返回数据,在asyncTask的doInBackGround中,会因为有空而崩溃
3.页面跳转前后,跳转前的数据没有准备好 ,
4.APP过多的使用全局变量 ,一旦发生内存回收,这些全局变量会被设置为空,而又没有考虑这种情况 。
1.方法需要对传入的参数判空或者try...catch后再继续使用
2.
3.调用外部接口确保返回值不为空,甚至确保执行该接口不会抛异常,导致程序的退出。
4.避免使用全局变量,不到万不得已不要使用全局变量,也要使全局支持序列号本地机制,一旦为空就通过fang
角标越界 IndexOutOfBoundsException(基类)
StringIndexOutOfBoundsException(字符串截取越界)
ArrayIndexOutOfBoundsException(数组越界)
  1.由于程序不严谨导致
2.在使用字符串时,经常使用subString(start ,end) 。start ,end超过字符串长度,就会崩溃 。

1.在遍历一个数组/集合时要预判数组集合是否为空 ,长度是否大于0;
2.在使用数组、集合中的元素时,要预判数组集合长度是否有那么长 。
试图调用一个空对象的方法 Attempt  to invoke virtual method on a null object reference
试图在一个空对象引用调用虚方法
  1.在一个activity中,调用另一个activity的方法 ,为此在B中建立一个static 变量 ,当这个static 变量被回收时 ,便会有异常。
2.推送 ,点击推送消息根据事先定好的协议,跳过首页直接进入二级甚至三级 。这时二级界面要是有首页的某个对象是,该对象势必为空。
没实例化
类型转换异常 ClassCastException:classA cannot be cast  to classB   Object x =new Integer(0)  ;
String str  =(String)x;
将安全类型转换函数 
把字符串转换为整数 小数或布尔类型时,我们要为指定转换失败时的默认值。否则,就会得到一个空值。
数字转换错误 NumberFormatException   在数据类型转换过程中 ,如果转换不成功,一般会抛出ClassCastException的异常 。有一个例外 ,字符型转换为数字失败时 ,时Android系统会抛出NumberFormatException异常 ( 
如String abc ="123****45"
    int result  =Integer.parseInt(abc) ;
这种情况发生在服务器返回数据没有按照约定返回整数而是字符串 ,客户端必须考虑到这种情况,如果转换失败,必须有默认值否则直接崩溃
声明数组长度为-1 NegativeArraySizeException   数组大小为负值异常 ,单前使用负数大小创建数组时抛出该异常。场景
String[] arg1 =new String[args.length -1] ; args没有元素时 。
如果数组长度是由另一个变量动态得到时 ,要保证中括号[] 中的值必须大于0
遍历集合的同时删除其中的元素 ConcurrModificationException   1.遍历一个集合不能删除该集合中的元素
2.多线程中删除同一个集合的元素(线程安全)
解决方案:需要再定义一个列表结合delList ,来保存需要删除的对象
比较器使用不当 comparsion method violates its general contrac   因为Comparator 的compare的方法使用的姿势不对(他是基于插入排序与归并排序算法相结合的产物 ,要比日常所用的冒泡排序算法快很多) (单元测试)
当除数为0 Java.lang.ArithmeticException:divide by zero   当程序中执行一个除法时 ,如果除数为0 ,就会发生该情况
.
 
不能随便使用aslist   AbstractList  (add    remove)
 子类    ArrayList  (add    remove)
            Arrays$Arraylist  (没有实现 (add  he remove)
 
找不到类(一) classNotFoundException   当我们动态加载一个类时候 ,如果该类运行时找不到,就会抛异常 如 
class.forName("com.company.package.class") ;
 由于类的全名称是字符串形式 ,这个很有可能是不正确 。
还有 findSystemClass("classname")
loadClass("classname") ;
 
找不到类(二) NoClassDefFoundError   ClassA obj= new ClassA() ; 打包B和A分别位于不同的dex中 ,这时在A所在的dex中把A类删除了
通常插件化编程会扯出这个异常因为要使用DexClassLOder。
 
activity 相关异常

     
找不到Activity Android content,activityNotFoundException:NO activty found to handle Intent{....}   1.错误原因  URL 不是以http开头 
Uri uti =Uri.parse("www.baidu.com"); 
Intent intent   =new Intent ........ 
2.打开SD卡上的一个html页面时 ,没有为Intent指定打开Html页面所需要的浏览器 
3.调用百度地图时openBaiduMapNavi 手机没有安装百度地图客户端 。(要判读是否安装)
 
不能实例化activity java.lang.RuntimeException:Unable to instantiate to activity ComponentInfo   1.通常没有AndroidManifext.xml  清单中注册activity  。
2.系统处于异常状态(内存不足)导致部件初始化 。

 
找到service Java.lang.RuntimeException:Unable to instance receiver   1.检查代码中是否有Class.forName("Class1")
2.ProGuard 会将class1 混淆 ,从而找不到这个类 。
 
不能启动BroadcastRece unable to start  reciver   1.在推送时,会和APP事先定义好协议,点击推送消息就跳过首页直接进入二级页面。
2.Content中有一个startActivity方法 ,Activity继承自Content ,重载startActivity方法,如果activity使用startActivity方法,不会有任何限制,如果使用Context的startActivity方法的话,就需要开启一个新的task,就需要开启一个新的task ,就会出现异常需要添加一个fiag
使用activity以外的content来startActivity ,比如BroadCastReceiver,就必须为Intent.FLAG_ACTIVITY_NEW_TASK,否则就会抛异常 。 
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivityForResult不能回传 failure delivering result ResultInfo{who=null  ,request =0 ;result=-1}   startActivityForResult,传回来的可key是A ,但按照B这个Key来取值  
猴急的fragment Fragment not attacher to Activity    因为fragment在还没有Attach到activity时,调用诸如getResource这样的方法 。
如getResource.getString(R.string.app_name) ;
解决方案 
if(isAdded){
getResources().getString(R.string.app_name)}
isAdd方法是Android系统提供的,它只有在fragment被添加到所属activity后才会返回ture。

序列号相关异常
     
实体对象不支持序列号 Parcelable encountered IOEXception writing serializable  object(name=xx)   如 :该类里面存在自定义实体 ,而该自定义实体未序列化。。。。  
序列化时未指定ClassLoader BadParcelableException:ClassNotFoundException when unmarshalling   在使用Parcelable 机制时 。
a =in.readParcelable(null) ;
private MyParcelable(Parcel in){ 
mStr =in.readString() ;
a=in.readParcelable(ClassA.class.getClassLoader())
}
ClassLoader classNotFoundException 。   当ClassLoader为空时系统采取默认的ClassLoader。
Android有两种ClassLoader:framework  classLoader和apk ClassLoader ,其中framework ClassLoader知道怎么加载Android的系统的内部的类 ;apk ClassLoader知道怎么加载我们自己写的类 ,也知道怎么加载Android系统的内部的类 。在APP刚启动时,默认的ClassLoader是apk ClassLoader ,但在系统内存不足应用会被系统回收再次启动的,这个默认的ClassLoader会变成framework ClassLoader  ,所以对于我们自己的类会报classNotFoundException 。
 
反序列化时发现类找不到:被ProGuard混淆导致的崩溃 parcelable  encountered ClassNotFoundException reading a  Serializable object ..   ProGuard 对于Class.forName(className)中的class无能为力,他会将这个class混淆的面目全非,于是在反序列化时找不到这个类。 在ProGuard中keep这个类
反序列化时发现类找不到:传入畸形数据
(安全漏洞)
Parcelable encountered  ClassNotFoundException reading a Serializable  object(name  =某个类名称)   1.由于正APP中使用getSeriaizableExtra() 的 api, 
APP开发人员没有对传入的数据做异常判断,别的有企图的人可以通过传入畸形数据,导致本地拒绝服务
2.传入简单数据,比如Integer  ,就会抛出类型转换异常classCastException
2.当传入自定义的可序列化对象时,就会抛出上述带有ClassNotException 的异常信息

 
反序列化时出错 Could  not read input  channel  file  description from parcel   一般是因为Intent 传递的数据太大 ,貌似大于1MB  就会崩溃。也有可能是fileDescripter太多而且没有关闭 ,或者looper太多没有退出导致的  
列表相关异常

     
adpter数据变化但是没有通知listview    adapter的内容变化了 ,但是相应的listview并不知情  1.保证adapter的数据在在主线程中修改
2.及时的调用notifyDataSetChange方法
         
listview滚动时点击刷新按钮后崩溃     滚动时调用getCount ,回调用getView,这时将数据clear了  。会报IndexOutOfBoundsException:Invalid  index  30 ,size  is  1 ; 在listview滚动时将刷新按钮设置为不可点击
Abslilstview 的obtainView  返回空指针 。   Abslilstview 的obtainView 方法获取不到view ,其原因在于getview方法在某些时候返回null getView的第二个常数convertView是不会为null ;
在getView返回值得时候,判断一下是否为null  ,如果为null ,则放回convertView 。
Adapter数据源发生变化但是没有notifyDataSetChanged   pageAdapter对于notifyDataSetChanged()和getCount()的执行顺序是非常严格的才,系统跟踪count的值 ,如果这个值和getCount返回值不一致,就会抛出这个异常 。 为了保证getCount总是返回一个正确的值 ,那么在初始化viewpage时应该先给adapter初始化内容后再将该adapter传递给viewpage ,如果不这样处理 ,在更新adapter的内容后 ,应该调用一下adapter的 notifyDataSetChanged 。

窗体相关的异常:基本上都是dissmiss方法销毁对话框的时候 ,activty已经不存在。
     
窗口句柄泄露   非主线程中的某些操作不当而引起的异常,从而导致强制关闭当前activity。而还未及时的调用dismss来解除Dialog等引用 。 在onDestroy()方法中调用dismiss来解除对dialog的引用 。
dialog.dismiss() ;
view not attached to widow manager   在一个费时的线程,在任务开始时显示对话框,任务结束时再销毁对话框,在期间如果activity因为某种原因有重新启动,那么Dialog调度dismiss方法的时候windowManager检查发现Dialog所属Activity已经不存在,所以会报
view not attached to widow manager

要正确使用对话框 ,
(1)不要在非UI线程中使用对话框创建显示和取消对话框 。,那么对于异步操作显示对话框怎么办?
Activty都要有相应的操作对话框回调 ,比如: 
.onCreateDialog .showDialog .dimissDialog  .removeDialog .
(2)一定要让对话框对象在activty的可控制范围内核生命周期之内。如对话框一定要是Activty的成员变量,并且再让对话框变量活跃在activty的Oncreat和OnDestory的方法之间 。
窗体在不恰当的时候获取了焦点。   在popoupWindow显示之前,就把焦点赋予它。
一般发生在Android2.3时出现
进行兼容。。。

token null  is not  for an application   在实现Android浮窗时 ,Context不正确 
AlertDialog.Builder(mcontext)所接的getAPPAction——Context()获取的Context,而应该是activty的实例,因为只有一个activty才能添加一个窗体。
 
permission  denied  for  this windown  type   在使用WindowMagnager.Layout.TYPE_SYSTEM_ALERT涉及window type 权限问题 。 解救办法的在配置文件中添加权限 
<!---显示系统窗口权限--> _ALERT_WINDOW
<!---在屏幕最顶部显示addview--> _OVERLAY_WINDOW

is your  activty running   1.当我回来,你已不在 。这种Crash 与弹窗密切相关 ,由于

2.在 onCreate 方法中 ,想要弹出PopupWindow,当参数parent为空时 ,就会报上述的错误,因为PopupWindow依赖于activty ,而activty的OnCreate还没执行完 ,那么肯定会报错。
2.可以通过延迟(handle)来实现这个效果。。。
添加窗体失败      
AlertDialog.resolveDialogTheme
  1.在B页写了一个show方法 ,控制AlertDialog的弹出和隐藏 。在A页面却要调用页面B页面的show方法,于是就崩溃了。
2.在TabActivty中切换Tab ,容易产生这个Crash ,因为在new对话框时,参数content指定成了this
,即指向当前子activty的content,但是子activty是动态创建的 ,不能保证一直存在,其父activity的content则是隐藏的,所以将this替换为getParent()即可,
1.
this specifiied childed already has a parent    在使用儿子时要先要调用其父的remove -view 方法,解除父子关系 。  
子线程不能修改UI       
不能再子线程操作AlterDialog和Toast      
资源相关的异常()

     
Resources$NotFoundException    因为参数int resID 错误 。我们把String 赋值给int的ResId ,所以编译器找不到正确的resource而报错误 。  
StackOverefiowError     Layout布局文件结构嵌套太深 ,我们应该尽量控制在5层以上 。要经常使用Hierarchy View对其进行优化,移除不必要的试图。 
在APP退出的时候APP有多个线程,那么在退出APP的时候可能不能完全关闭APP,及时使用finish方法也无法做到 ,必须使用System.exit(0)这样的语句才可以。这是因为finish方法只能退出当前的activity ,但是还有其他activty未关闭,这些activty中没有结束的线程,从而还有一些资源没有释放。而exit(int code)方法可以使进程退出能保证把所有的线程的栈空间释放,否则会有线程残留空间无法释放从而无法回收。将会导致该进程新建时栈空间不足,从而发生StackOverefiowError异常。
无论哪种StackOverefiowError异常都是由于无线递归引起的,在JVM中有一个栈,预设了一个深度,当超出这个深度时就会抛出StackOverefiowError。
unstatisfiedLinkError   .so格式的文件没有加载到 ,检查libs的aremeabi目录下的.so文件是否存在 。不能只看aremeabi 还要看x86下.so文件是否存在,如果没有,在x86的设备上依然是加载不到的。 cpu指令集在Android aremeabi aremeabi-v7a mips 和   x86 ,所以处理so文件要格外小心  。
aremeabi 与 aremeabi-v7a 的so数量不一致,是典型的会导致UnsatisfiedLinkError的场景
infiateException之FileNotFoundException   GC导致 ,activty被销毁但涉及的资源没有被回收,便产生内存泄露,但是表现为FileNotFoundException 在activty的onStop方法中手动释放每一张图片的资源
infiateException之缺少构造器   在创建自定义View的时候,会可能产生。
是其中第二个参数用来将xml文件中的属性初始化。
在自定义控件若需要xml文件中使用,就必须重写带上两个参数的构造方法 。
infiateException之style与android:textstyle的区别   style中定义 要用 style=“@style/NomalText”  
TransactionTooLargeException   Binder最大通常为1MB ,如果大于1MB就会抛出TransactionTooLargeException 异常 。 
这个异常经常出现在图片的分享功能中。
在采集打点数据时也会看到这类异常 ,(数据积累到一定量后才发生的)
不要将大量的数据传入Binder 不如说图片

系统碎片化化异常(一是版本差异 二是不同的ROM)
     
NosuchMethodError java.lang.NoSuchMethErroor   方法被放弃,谨慎使用 。 在开发阶段Android Lint,里面又被废弃方法的警告。
如果使用要进行Android  系统版本的判断。 
int sysVersion =Integer.paresInt(android.os.Build.VERDION.SDK) ;
if.....
RemoteViews android.widget.RemoteView$Refiection.writeToParcel(Remote.java:763)   RemoteViews使用的地方有两个 ,
APPWidget ,Notification。对于APP类而言有机会用到的是后者。
Notification 有一个contentView属性,就是RemoteView类型 。给imageview设置图片  textVie
绑定资源ID 。

异常:当Bitmap为null时
     当你的string 为""或者为null 
   Android版本是4.1时 不会出现以上情况。只会表现出异常并不会大致程序崩溃
pointerIndex out of  range java.lang.IllegalArgumentException:pointerIndex out of rangeat android view .motionEvent.nationGetAxiValue(Native Method)   在做多点触控放大缩小,操作自己所绘制的图形时发生这个异常,如果是操作图片的方法缩小,多点触控不会出现这个错误 。这个bug是Android系统原因导致的,所以简单有效的办法是在绘制时捕获这个异常 。

在用viewpage的话 ,onInterceptTouchEvent返回false 会导致viewpage翻页出现bug 。  
方法一:
public  fioat spacing (MotionEvent event){
try{ 
x =event.getX(0) -event.getX(i) ;
y=event.get(0)-event.getY(i);
}catch(IllegalArgumentException){
e.printStackTrance() ;
}
}


方法二:1.让view创建一个子view继承自它们中的某一个。
2.重写这个 view的onInterceptTouchEvent和onTouchEvent
3.为上述这个两个方法增加try。。catch语句,捕获已知的异常 。
try{ 
 super.onIntercepttouchEvent(MotionEvent ev)
}catch(IllegalArgumentException){
e.printStackTrance() ;
}
try{ 
 super.onTouchEvent(MotionEvent ev)
}catch(IllegalArgumentException){
e.printStackTrance() ;
}
至少在4.1 上是好用的。
securityException 之一 Intent中的图片太大   在跳转的extra中有bitmap应该减少要传输的图片的体积大小,或者通过保存图片的SD卡中或者通过URI方式传递图片参数,否则,图片太大,就会有上述错误。1MB是一个临界点 。  
SecurityException 之二 动态加载其他的apk的activity 。   如果在apk中动态的注册Broadcast ,那么Launcher动态加载该apk时 ,就有可能出现java.lang.secuityException异常  修改之前注册的BroadcastReceiver的地方 ,通过ContextHOder()来=注册BroadcastReceiver ,把apk重新部署验证即可 。
SecurityException 之三 No permission to modify thread    App经常会申请一些权限 ,而有些手机的ROM处于安全考虑,会禁止这些权限 ,那么当APP使用这些权限时 ,就会发生崩溃 。 在执行某些安全相关的操作时 ,要么加if语句跳过要么使用try...catch..  捕获这类异常 ,宁肯点击无效也不能崩溃 。如电话拨打 有些手机会禁止 。即使在功能清单文件中配置了页不行 ,我们要先判断是否有打电话的权限,以确保不发生崩溃 。
view的getDrawingCache()返回null   当背景图太大,超过屏幕的大小 ,就导致getDrawingCache()返回的结果是null ,从而抛出NullPointEXception 异常 控制图片的大小 ,剪裁或者等比缩放 。
DeadObjectException        
anderoid  2.1 不支持SSL    版本判断  
viewFlipper   横竖屏切换引发的异常是由于onDetachedFromWindow()在onAttachedToWindow()  ; 重写viewFlipper的OnDetachedFromWindow()方法
ActivtyNotFoundException   发生在4.0 以上出现  。原因 ,是4.0
以上用来的网络设置方式舍弃了 。
 
Android2.2 不支持xlargeScreens NO resource identifier found  for  attribute ‘xlargeScreens’in package  ‘Android’   在功能清单文件中supports-scress标记中 ,原因xlargeScreens  属性在API9(2.3)中才支持 。  
package manager  has died Package  manager  has died  at android.app.applicationPackageManager.getApplication(ApplicationPackageManager.java..)    
spannableString 与富文本字符串      
can not perfform  this action  after onSaveInstanceState   commit方法在activity的OnSaveInstanceState()之后调用 ,因为。。。  
service Intent  must  be  explicit service Intent  must  be  explicit   在5.0系统后会产生这样的崩溃 ,直接通过action启动service ,就会导致这个问题  ,必须指定component 或者package 才能避免这类问题 。
SqLite相关异常

     
No transaction is active        
忘记关闭Cursor        
数据库被锁定        
试图再打开已经关闭的对象        
文件加密了或无数据库        
webview中的Sqlite 缓存导致的崩溃        
webview中的cache数据        
磁盘读写错误        
android_metadata表不存在        
android_metadate表中的locale字段        
数据库或者磁盘满了        

不明错误
     
内存溢出        
verify Failed        
TimeOutException        
json  解析异常        
jsonArray在初始化时为空        
第三方SDK 抛出的crash        
两个不同类型的view有相同的id        
LayoutInfiater.from().infitate()使用不当导致的崩溃        
viewgroup        
monkey点击过快导致的崩溃        
图片缩放很多倍        
图片宽度为0        
不能重复添加组件        
         





posted @ 2016-09-07 16:35  画戟  阅读(864)  评论(0编辑  收藏  举报