最近优化项目,就改了bugly上报的一些异常,写个文章记录一下,以后忘记了可以查阅。

一、java.lang.NullPointerException
该异常表示尝试去调用virtual method,使用了一个空对象引用,建议检查引用的对象是否为空。
[解决方案]:这种异常通常是调用一个对象的方法抛出的,凡是调用一个对象的方法之前,一定要进行判空或者进行try-catch,这样基本可以规避大部分空指针异常。

二、java.lang.IndexOutOfBoundsException 或java.lang.ArrayIndexOutOfBoundsException
该异常表示不合法下标,通常是因为访问了list或array不合法的位置,建议检查数据是否越界。
[解决方案]:
1.遍历数组/字符串等集合前,要判断遍历对象的长度;
2.操作数组/字符串等集合前,要检查角标是否在长度允许范围内;
2.ListView操作不当也会引起该异常,这种情况下一般是由于List渲染的时候,外面的数据源发生变化导致的。举例如ListView滚动时点击刷新将会报错,解决方法是ListView滚动时将刷新置为不可点击。

三、java.lang.NumberFormatException
[解决方案]:
数字格式化异常。当试图将一个String转换为指定的数字类型,而该字符串确不满足数字类型要求的格式时,抛出该异常(字符串不能为""或null)

四、java.lang.ClassNotFoundException
[解决方案]:
该异常表示在路径下,找不到指定类,通常是因为构建路径问题导致的。
[解决方案]:类名是以字符串形式标识的,可信度比较低,在调用Class.forName(""),Class.findSystemClass(""),Class.loadClass("")等方法时,找不到类名时将会报错。如果找不到的Class是系统Class,那么可能是系统版本兼容,厂家Rom兼容的问题,找到对应的设备尝试重现,解决方法可以考虑更换Api,或用自己实现的Class替代。
如果找不到的Class是应用自由Class(含第三方SDK的Class),可以通过反编译工具查看对应apk中是否真的缺少该Class,再进行定位,这种往往发生在:
1.要找的Class被混淆了,存在但名字变了;
2.要找的Class未被打入Dex,确实不存在,可能是因为自己的疏忽,或编译环境的冲突;
3.要找的Class确实存在,但你的Classlorder找不到这个Class,往往因为这个Classloder是你自实现的(插件化应用中常见)。

五、java.util.ConcurrentModificationException
并发修改异常,该异常表示迭代器迭代过程中,迭代的对象发生了改变,如数据项增加或删除。
[解决方案]:由于迭代对象不是线程安全,在迭代的过程中,会检查modCount是否和初始modCount即expectedModCount一致,如果不一致,则认为数据有变化,迭代终止并抛出异常。常出现的场景是,两个线程同时对集合进行操作,线程1对集合进行遍历,而线程2对集合进行增加、删除操作,此时将会发生ConcurrentModificationException异常。
具体方法:多线程访问时要增加同步锁,或者建议使用线程安全的集合:
1. 使用ConcurrentHashMap替换HashMap,CopyOnWriteArrayList替换ArrayList;
2. 或者使用使用Vector替换ArrayList,Vector是线程安全的。Vector的缺点:大量数据操作时,由于线程安全,性能比ArrayList低.

六、java.lang.OutOfMemoryError
Could not allocate JNI Env

OutOfMemoryError异常的常见原因有以下几种:

1.内存中加载的数据量过于庞大,如一次从数据库取出过多数据;
       2.集合类中有对对象的引用,使用完后未清空,使得JVM不能回收;
       3.代码中存在死循环或循环产生过多重复的对象实体;

解决方案

加载数据过多的时候选择分页加载,不要在循环中大量创建对象。

OOM是常见的java错误,OOM主要有:
1.OOM fo heapjava.lang:OutOfMemoryError: Java heap space,此OOM是由于JVM中heap的最大值不满足需要,将设置heap的最大值调高即可。
2.OOM for Perm:java.lang:OutOfMemoryError: Java perm space,此OOM是由于JVM中perm的最大值不满足需要,将设置perm的最大值调高即可,参数样例为:-XX:MaxPermSize=512M
3.OOM for GC=>例如:java.lang:OutOfMemoryError: GC overhead limit exceeded,此OOM是由于JVM在GC时,对象过多,导致内存溢出,建议调整GC的策略
4.OOM for native thread created:java.lang.OutOfMemoryError: unable to create new native thread,此OOM是由于进程剩余的空间不足,导致创建进程失败
5.OOM for allocate huge array:Exception in thread "main": java.lang.OutOfMemoryError: Requested array size exceeds VM limit,此类信息表明应用程序(或者被应用程序调用的APIs)试图分配一个大于堆大小的数组
6.OOM for small swap:Exception in thread "main": java.lang.OutOfMemoryError: request <size> bytes for <reason>. Out of swap space?,抛出这类错误,是由于从native堆中分配内存失败,并且堆内存可能接近耗尽
7.OutOfMemoryError thrown while trying to throw OutOfMemoryError; no stack trace available,抛出这类错误,一般是由于方法重复调用、死循环引起,直至内存耗尽

七、java.lang.IllegalArgumentException
View=DecorView@9de4b14[MainActivity] not attached to window manager
android.view.WindowManagerGlobal.findViewLocked(WindowManagerGlobal.java:547)
该异常表示view没有添加到窗口管理器,通常是我们dismiss对话框的时候,activity已经不存在了,建议不要在非UI线程操作对话框。
[解决方案]:常发生这类Exception的情形都是,有一个费时的线程操作,需要显示一个Dialog,在任务开始的时候显示一个对话框,然后当任务完成了在Dismiss对话框,如果在此期间如果Activity因为某种原因被杀掉且又重新启动了,那么当dialog调用dismiss的时候WindowManager检查发现Dialog所属的Activity已经不存在,所以会报错。
要避免此类Exception,就要正确的使用对话框,也要正确的使用线程:
1.不要在非UI线程中使用对话框创建,显示和取消对话框;
2.尽量少用单独线程,出发是真正的耗时操作采用线程,线程也不要直接用Java式的匿名线程,除非是那种单纯的操作,操作完成不需要做其他事情的。
3.如果是在fragment中发起异步网络的回调中进行dialog的操作,那么在操作之前,需要判断 isAdd( ),避免fragment被回收了但是还要求dialog去dismiss
4.在Activity onDestroy中对Dialog提前进行关闭

八、java.lang.NoSuchFieldError
No static field general_type_item_video_call of type I in class Lcom/feinnoui/library/R$string; or its superclasses (declaration of 'com.feinnoui.library.R$string' appears in /data/app/com.bankcomm.jrt-2/split_lib_slice_8_apk.apk)
域不存在错误。当应用试图访问或者修改某类的某个域,而该类的定义中没有该域的定义时抛出该错误
NoSuchFieldError是Java反射中的一个异常,其表示无法通过反射找到需要的字段。
本次出现这个问题是项目中做了国际化适配,英文版的少了这个资源id,编译的时候没有出错,用户切为英文环境的时候,就报出了这个错。
[解决方案]:加上指定的资源。

九、java.lang.ClassCastException

类型转换异常。当试图将一个类型转换为指定的类型,而该类型却不是同一个类型时,抛出该异常

问题出现原因:JVM在做类型转换时会按照如下规则进行检查:

对于普通对象,对象必须是目标类的实例或目标类的子类的实例。如果目标类是接口,那么会把他当作实现了该接口的一个子类。
        对于数组类型,目标类必须是数组类型或java.lang.Object、java.lang.Cloneable、java.io.Serializable。

如果不满足上面的规则,JVM会报这个错误了。
[解决方案]:先用 instanceof判断数据类型,然后再强转。

十、java.lang.IllegalStateException

java.lang.IllegalStateException异常产生的原因及解决办法  
错误类型大致为以下几种:
1.java.lang.IllegalStateException:Cannot   forward   a   response   that   is   already   committed
IllegalStateException:response already commited
IllegalStateException:getOutputStream() has already been called for this request
…………
IllegalStateException: Can not perform this action after onSaveInstanceState:
#解决办法:onSaveInstanceState方法是在该Activity即将被销毁前调用,来保存Activity数据的,如果在保存玩状态后
再给它添加Fragment就会出错。解决办法就是把commit()方法替换成 commitAllowingStateLoss()
错误原因:
  该异常表示,当前对客户端的响应已经结束,不能在响应已经结束(或说消亡)后再向客户端(实际上是缓冲区)输出任何内容。
  Object is no longer valid to operate on. Was it deleted by another thread?
  该异常表示,realmObject对象在其他线程已被删除,在这个线程中使用的时候抛出的异常。
具体分析:
首先解释下flush(),我们知道在使用读写流的时候数据先被读入内存这个缓冲区中, 然后再写入文件,但是当数据读完时不代表数据已经写入文件完毕,因为可能还有一部分仍未写入文件而留在内存中,这时调用flush()方法就会把缓冲区的数据强行清空输出,因此flush()的作用就是保证缓存清空输出。response是服务端对客户端请求的一个响应,其中封装了响应头、状态码、内容等,服务端在把response提交到客户端之前,会向缓冲区内写入响应头和状态码,然后将所有内容flush。这就标志着该次响应已经committed(提交)。对于当前页面中已经committed(提交)的response,就不能再使用这个response向缓冲区写任何东西(注:同一个页面中的response.XXX()是同一个response的不同方法,只要其中一个已经导致了committed,那么其它类似方式的调用都会导致 IllegalStateException异常)。

2.java.lang.IllegalStateException
Can't change tag of fragment d{e183845 #0 d{e183845}}: was d{e183845} now d{e183845 #0 d{e183845}}
经查,我在显示fragment的代码中使用了:
fragment.show(getSupportFragmentManager, fragment.toString());
而这里是因为两次toString()结果不同,导致不同的tag指向的是同一个fragment。
获取fragment的tag的正确方法应该是使用其提供的fragment.getTag()方法。

3.java.lang.IllegalStateException
Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 37 path $.data
错误原因:该异常是由于服务器错误返回的JSON字符串和服务器正常下时返回的JSON字符串结构不同,导致利用Gson解析的时候报了一个异常:本该去解析集合却强制去解析对象所致.
解决办法:在使用Gson解析JSON时try cash一下,不报错按照正常逻辑继续解析,报异常则处理为请求失败逻辑即可.
数据库相关的Exception
4.android.database.CursorWindowAllocationException
Cursor window allocation of 2048 kb failed.
该异常表示游标窗口分配内存失败,通常是使用Cursor不当导致的内存泄漏。
[解决方案]:建议检查工程中所有使用Cursor对象的地方,保证使用后及时关闭。另外,加强内存泄露测试,可以提前发现此类问题。
5.java.lang.IllegalStateException
Not allowed to start service Intent { cmp=com.bankcomm.jrt/com.chinamobile.uc.emplistsdk.service.CoreService }: app is in background uid UidRecord{df3345e u0a128 LAST bg:+1m5s762ms idle procs:2 seq(0,0,0)}
错误原因:Android 8.0 不再允许后台service直接通过startService方式去启动。
[解决方案]:改为startForegroundService方式启动即可(注意:用此方法开启service,必须在5S内调用startForeground())。

十一、android.database.sqlite.SQLiteDatabaseLockedException
database is locked (Sqlite code 5): , while compiling: PRAGMA journal_mode, (OS error - 2:No such file or directory)
数据库文件被锁定,两个地方同时访问数据库的时候出现此异常。
[解决方案]:建议将 SQLiteOpenHelper 写成单例模式的,这样就能保证同一时间内只能有一个 SQLiteOpenHelper 访问 sqlite 数据库,避免同时有两个 SQLiteOpenHelper 访问 sqlite 报错的情况发生。

十二、net.sqlcipher.database.SQLiteException
file is not a database: , while compiling: select count(*) from sqlite_master;
文件不是db文件,在用sqlcipher进行加密后,重新调用未加密的库的时候出现的Exception
[解决方案]:
1.要求用户卸载安装,或者加密之后做好兼容,删除原有数据库文件,重新建库建表(优点,操作简单,缺点:丢失原有数据)。
2.读取旧数据库中的数据,复制表到新的数据库。

十三、java.lang.InternalError
Thread starting during runtime shutdown
java.lang.Thread.nativeCreate(Native Method)
android.app.RemoteServiceException
该异常表示发生了内部错误,而这个错误是线程在runtime宕机时启动造成的。
[解决方案]:这类问题一般是是线程开启的太晚了导致的。我们启动一个线程会调用Thread的start方法,start方法会调用名为nativeCreate的本地方法,具体位置在/android/art/runtime/native/java_lang_Thread.cc,名字换成了CreateNativeThread:我们可以看看它的源码:
 void Thread::CreateNativeThread(JNIEnv* env, jobject java_peer, size_t stack_size, bool is_daemon) {
CHECK(java_peer != nullptr);//即为java层的thread实例,包裹着run方法的具体实现
  Thread* self = static_cast<JNIEnvExt*>(env)->self;
  Runtime* runtime = Runtime::Current();
  // Atomically start the birth of the thread ensuring the runtime isn't shutting down.
  bool thread_start_during_shutdown = false;//这段代码用来检测thread是否在runtime宕机时start的
  {
    MutexLock mu(self, *Locks::runtime_shutdown_lock_);
    if (runtime->IsShuttingDownLocked()) {
      thread_start_during_shutdown = true;
    } else {
      runtime->StartThreadBirth();
    }
  }
  if (thread_start_during_shutdown) {//若runtime宕机了就抛出异常
    ScopedLocalRef<jclass> error_class(env, env->FindClass("java/lang/InternalError"));
    env->ThrowNew(error_class.get(), "Thread starting during runtime shutdown");
    return;
  }
..... 省略代码

从代码我们可以知道,如果runtime宕机了就会抛出InternalError的异常。我们在启动线程的时候,需要确认一下是否有线程嵌套的情况,不要在线程中再去启动一个线程。

十四、Context.startForegroundService() did not then call Service.startForeground()
android.app.ActivityThread$H.handleMessage(ActivityThread.java:1855)
问题出现场景:
远程服务异常,在android8.0开启服务时遇到,因为8.0对于服务的管理,不允许后台开启服务,所以必须把服务置于前台,这时候就必须在被开启服务的onCreate方法中调用startForeground()方法,如果在5S之内没有调这个方法,便会爆出上述异常。
该异常表示从Package发布通知时存在异常,主要出现在通知栏更新。
[解决方案]:出现这个异常的原因有很多,使用通知需要注意以下几点:
1.每次更新时都需要实例化Notification;
2.设置Notification的ContentView之后记得设置ContentIntent;
3.如果使用了RemoteViews时,需要保证包名的正确性;
4.注意各个系统版本对于Notification使用方法的差异性。

十五、android.os.RemoteException
Remote stack trace: at com.android.server.am.ActivityManagerService.killBackgroundProcesses(ActivityManagerService.java:7519) at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:1231) at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:3632) at com.android.server.am.HwActivityManagerService.onTransact(HwActivityManagerService.java:628) at android.os.Binder.execTransact(Binder.java:739)
java.lang.RuntimeException:Unable to pause activity {com.bankcomm.jrt/com.feinnoui.library.ui.activitys.chat.SingleChatActivity}: java.lang.SecurityException: Permission Denial: killBackgroundProcesses() from pid=25580, uid=1010178 requires android.permission.KILL_BACKGROUND_PROCESSES
[解决方案]:缺少后台杀进程的权限KILL_BACKGROUND_PROCESSES,加上就好

十六、android.content.ActivityNotFoundException
Unable to find explicit activity class {com.bankcomm.jrt/com.feinnoui.library.ui.activitys.contact.LocalContactCardActivity}; have you declared this activity in your AndroidManifest.xml?
该异常表示找不到指定的Activity。
[解决方案]:
1.检查AndroidManifest文件,是否注册了对应的Activity:
<activity
    android:name="com.tencent.bugly.testActivity"
    android:label="@string/app_name">            
</activity>"
2.系统版本或厂商兼容性问题,如在高版本中调用了低版本已经废弃的Activity,建议对这类问题加强适配测试,添加特殊处理;
3.通过反编译工具检查该Activity类是否已经打入Apk。
4.调起第三方应用界面也有可能出现此问题

十七、android.view.WindowManager$BadTokenException
Unable to add window -- token android.os.BinderProxy@9f75caa for displayid = 0 is not valid; is your activity running?

该异常出现原因是由于将要弹出的dialog所要依附的View已经不存在导致的。

出现场景:当界面销毁后再弹出来;或者界面跳转时我们的view发生改变,dialog依附的context发生变化或者界面未运行了。

此外,很多时候我们需要通过一个非组件类来调用一个view类的方法来弹出dialog或Toast,这样就需要再提供一个静态context来创建这个dialog或者Toast

[解决方案]:

1.对于tab页出现的错误可以用其父类的context来弹出dialog;  对于界面已经销毁引起的错误就只能判断界面是否存在然后再弹出了;

2.对于利用静态context来弹出的dialog可以通过规避的方式来解决,比如避免出现静态context被修改。。但是这样就可能限制了我们程序的功能。。

3.因此我们可以通过在bind数据时时时更新这个静态context就可以解决此问题了,这样就可以保证这个静态的context在任何view中都是当前的界面的view的context。就不会出现找不到其父类window了。

4.在关闭PopupWindow或者dialog时,要先关闭PopupWindow或者dialog,再关闭Activity,PopupWindow或者dialog不能独立存在。

十八、Only fullscreen activities can request orientation

问题出现原因,谷歌在安卓8.0版本时为了支持全面屏,增加了一个限制:如果是透明的Activity,则不能固定它的方向,因为它的方向其实是依赖其父Activity的(因为透明)。然而这个bug只有在8.0中有,8.1中已经修复。具体crash有两种:

1.Activity的风格为透明,在manifest文件中指定了一个方向,则在onCreate中crash

2.Activity的风格为透明,如果调用setRequestedOrientation方法固定方向,则crash
[解决方案]:参考:https://blog.csdn.net/starry_eve/article/details/82777160

持续更新~~~~

android中常见的异常总结相关推荐

  1. Android中常见的MVC/MVP/MVVM模式

    Android中常见的MVC/MVP/MVVM模式 经典MVC 在1979年,经典MVC模式被提出. 在当时,人们一直试图将纯粹描述思维中的对象与跟计算机环境打交道的代码隔离开来,而Trygve Re ...

  2. Android中常见的内存泄露

    内存泄漏是指无用对象(不再使用的对象)持续占有内存或无用对象的内存得不到及时释放,从而造成内存空间的浪费称为内存泄漏.内存泄露有时不严重且不易察觉,这样开发者就不知道存在内存泄露,但有时也会很严重,会 ...

  3. Android中常见布局

    android中常见布局 [1]线性布局 水平 垂直. <?xml version="1.0" encoding="utf-8"?> <Lin ...

  4. Android开发——Android中常见的4种线程池(保证你能看懂并理解)

    0.前言 转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52415337 使用线程池可以给我们带来很多好处,首先通过线程池中线程的重用 ...

  5. Android中常见的4种线程池的理解(转)

    转:https://blog.csdn.net/l540675759/article/details/62230562 转:https://blog.csdn.net/seu_calvin/artic ...

  6. Android中处理崩溃异常

    2019独角兽企业重金招聘Python工程师标准>>> 大家都知道,现在安装Android系统的手机版本和设备千差万别,在模拟器上运行良好的程序安装到某款手机上说不定就出现崩溃的现象 ...

  7. android 中处理崩溃异常并重启程序

    转:http://blog.csdn.net/cym_lmy/article/details/24704089 有时候由于测试不充分或者程序潜在的问题而导致程序异常崩溃,这个是令人无法接受的,在and ...

  8. Java中常见的异常

    作为一名游戏开发者,程序员,很自然必须熟悉对程序的调试方法.而要调试程序,自然需要对程序中的常见的异常有一定的了解,这些日子很多朋友都提出了很多问题,都是关于游戏中的报错,因此在这里我将一些常见的程序 ...

  9. java中常见的异常类

    1. java.lang.nullpointerexception 这个异常大家肯定都经常遇到,异常的解释是"程序遇上了空指针",简单地说就是调用了未经初始化的对象或者是不存在的对 ...

  10. Android中常见的MVC模式

    MVC模式的简要介绍 MVC是三个单词的缩写,分别为: 模型(Model),视图(View)和控制Controller). MVC模式的目的就是实现Web系统的职能分工. Model层实现系统中的业务 ...

最新文章

  1. java中unknown source_java中GUI编程中的unknown source问题
  2. matlab中并行用不了,请教matlab在linux下的并行问题 - 程序语言 - 小木虫 - 学术 科研 互动社区...
  3. 后退键无效 html,javascript – Cordova – window.history.back()不支持iOS 9中的HTML后退按钮...
  4. 【CSAPP】三、程序的机器级表示
  5. 006_Redis的List数据类型
  6. 《c语言从入门到精通》看书笔记——第16章 网络套接字编程(下)——套接字
  7. 【渝粤题库】陕西师范大学201371 国际法学作业
  8. 前端小知识点(2):普通字符串和new String有什么区别
  9. 护航Lazada双11购物节 阿里云CDN全球化火力全开
  10. 计算机过去和现在的变化英语作文,自己过去和现在的变化英语作文带翻译
  11. linux shell下除了某个文件外的其他文件全部删除的命令
  12. php js 交互(js调用PHP代码执行)
  13. tablelayout高度问题
  14. html在线随机出题系统,出题系统/考试模拟考试系统-在线系统
  15. Google Play App送审被拒-违反权限政策
  16. Hadoop+Spark 之旅—脚踏实地、仰望星空(教程目录)
  17. 想成为注塑模具设计高手:这个你一定要懂
  18. 《春风十里不如你》身体骚动的魔性,精神成长的传记
  19. 关于机器人进展的一些个人看法
  20. Google Chrome无法访问网站的原因与解决办法

热门文章

  1. 计算机怎么更换硬盘,如何更换电脑新硬盘无需重装系统_换硬盘不重装系统方法...
  2. stm32f7网口_【STM32F7】开发篇 - 详解STM32F7 TCPServer工程【申精】
  3. 华硕路由器配置虚拟服务器,华硕ASUS路由器无线中继模式设置步骤图解
  4. NLP之TF之LSTM:基于Tensorflow框架采用PTB数据集建立LSTM网络的自然语言建模
  5. 手机怎么模拟125k卡_NFC手机能模拟门禁卡吗?
  6. 【Flutter实战静态页面】--在线点餐app(7)——页面跳转
  7. 祝新年快乐html小程序,小程序网页开发真诚的祝福大家2018...
  8. 易捷行云新一代私有云全场景智能统一运维|轻运维之场景化运维
  9. Proximal Policy Optimization(PPO)算法原理及实现!
  10. VMware虚拟机安装Ubuntu系统步骤详解