首页 > 代码库 > 异常分析 (空间太小)

异常分析 (空间太小)

  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) ;
这种情况发生在服务器返回数据没有按照约定返回整数而是字符串 ,客户端必须考虑到这种情况,如果转换失败,必须有默认值否则直接崩溃
声明数组长度为-1NegativeArraySizeException 数组大小为负值异常 ,单前使用负数大小创建数组时抛出该异常。场景
String[] arg1 =new String[args.length -1] ; args没有元素时 。
如果数组长度是由另一个变量动态得到时 ,要保证中括号[] 中的值必须大于0
遍历集合的同时删除其中的元素ConcurrModificationException 1.遍历一个集合不能删除该集合中的元素
2.多线程中删除同一个集合的元素(线程安全)
解决方案:需要再定义一个列表结合delList ,来保存需要删除的对象
比较器使用不当comparsion method violates its general contrac 因为Comparator 的compare的方法使用的姿势不对(他是基于插入排序与归并排序算法相结合的产物 ,要比日常所用的冒泡排序算法快很多)(单元测试)
当除数为0Java.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 相关异常

   
找不到ActivityAndroid 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 手机没有安装百度地图客户端 。(要判读是否安装)
 
不能实例化activityjava.lang.RuntimeException:Unable to instantiate to activity ComponentInfo 1.通常没有AndroidManifext.xml  清单中注册activity  。
2.系统处于异常状态(内存不足)导致部件初始化 。

 
找到serviceJava.lang.RuntimeException:Unable to instance receiver 1.检查代码中是否有Class.forName("Class1")
2.ProGuard 会将class1 混淆 ,从而找不到这个类 。
 
不能启动BroadcastReceunable 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来取值 
猴急的fragmentFragment 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) 如 :该类里面存在自定义实体 ,而该自定义实体未序列化。。。。 
序列化时未指定ClassLoaderBadParcelableException:ClassNotFoundException when unmarshalling 在使用Parcelable 机制时 。
a =in.readParcelable(null) ;
private MyParcelable(Parcel in){ 
mStr =in.readString() ;
a=in.readParcelable(ClassA.class.getClassLoader())
}
ClassLoaderclassNotFoundException 。 当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方法在某些时候返回nullgetView的第二个常数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)
   
NosuchMethodErrorjava.lang.NoSuchMethErroor 方法被放弃,谨慎使用 。在开发阶段Android Lint,里面又被废弃方法的警告。
如果使用要进行Android  系统版本的判断。 
int sysVersion =Integer.paresInt(android.os.Build.VERDION.SDK) ;
if.....
RemoteViewsandroid.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  rangejava.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 不支持xlargeScreensNO resource identifier found  for  attribute ‘xlargeScreens’in package  ‘Android’ 在功能清单文件中supports-scress标记中 ,原因xlargeScreens  属性在API9(2.3)中才支持 。 
package manager  has diedPackage  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  explicitservice 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    
不能重复添加组件    
     



来自为知笔记(Wiz)



异常分析 (空间太小)