在我们开发的过程中,再厉害的程序员也无法保证写的代码没有错误,而这里面最严重的错误,对于android开发来说,毫无疑问就是app闪退了.特别是在开发第三方SDK的时候,假设因为SDK里面报的问题,导致对方App崩溃了,这对SDK而言的打击是非常严重的,有的时候我们甚至希望SDK即使无法很好的工作,也不要引发对接方App的崩溃.
下面我就来介绍两种,可以根据代码判断,只会代码所在线程死掉,但不会引发崩溃的方法:
- hook Thread.UncaughtExceptionHandler 的方式
- 代理 Thread.UncaughtExceptionHandler 的方式
hook Thread.UncaughtExceptionHandler 的方式
第一种方式就是,我们在程序启动的时候,先使用Thread.getDefaultUncaughtExceptionHandler();拿到系统的错误处理Handler对象,再次之上,我们自己创建一个 Thread.UncaughtExceptionHandler 的继承类,包裹住系统的错误处理Handler对象之后,把我们自己创建的Thread.UncaughtExceptionHandler 传递回去.
系统的Thread.UncaughtExceptionHandler的实现类是com.android.internal.os.RuntimeInit$UncaughtHandler
hook代码如下:
public void hook() {
Thread.UncaughtExceptionHandler ueh = Thread.getDefaultUncaughtExceptionHandler(); if (ueh == null) {
mSystemUeh = null; mOtherUeh = null; Thread.setDefaultUncaughtExceptionHandler(CrashHookImpl2.this); return; } String androidUeh = "com.android.internal.os.RuntimeInit$UncaughtHandler"; String selfUeh = getClass().getName(); String currUeh = ueh.getClass().getName(); //系统的 if (androidUeh.equals(currUeh)) {
mSystemUeh = ueh; mOtherUeh = null; Thread.setDefaultUncaughtExceptionHandler(CrashHookImpl2.this); } else if (selfUeh.equals(currUeh)) {
//自己人 不处理 } else {
// bugly的 -> currUeh.contains("com.tencent.bugly.crashreport.crash") mSystemUeh = null; mOtherUeh = ueh; Thread.setDefaultUncaughtExceptionHandler(CrashHookImpl2.this); } return; }
讯享网
其中,CrashHookImpl2是我们继承自Thread.UncaughtExceptionHandler 自己的实现类, 其中uncaughtException实现如下:
讯享网 @Override public void uncaughtException(Thread t, Throwable e) {
//-----------自己的处理,拦截除0异常------------------------------- StackTraceElement[] elements = e.getStackTrace(); for (int i = 0; i < elements.length; i++) {
if (e.getClass().getName().equals("java.lang.ArithmeticException")) {
return; } } //-----------下面的系统的uncaughtException不走,既不会崩溃--------- if (mOtherUeh != null) {
mOtherUeh.uncaughtException(t, e); } if (mSystemUeh != null) {
mSystemUeh.uncaughtException(t, e); } }
这时候, 我们可以在程序中写一个除以0 的异常,则是不会引发崩溃的,只会引发线程的停止:
CrashHookImpl.getInstance().hook(); CrashHookImpl.getInstance().addCutOffExceptionHandler(new CrashHook.CutOffExceptionHandler() {
@Override public boolean onCutOffException(Thread t, Throwable e) {
StackTraceElement[] elements = e.getStackTrace(); for (int i = 0; i < elements.length; i++) {
if (e.getClass().getName().equals("java.lang.ArithmeticException")) {
return true; } } return false; } }); new Thread() {
@Override public void run() {
while (true) {
try {
Thread.sleep(1000); } catch (InterruptedException e) {
e.printStackTrace(); } System.out.println(100 / 0 + "hook"); String nullp = null; int a = nullp.length(); } } }.start();
实现类全部代码:
讯享网 import android.os.Build; import android.os.Handler; import android.os.HandlerThread; import java.util.ArrayList; import java.util.List; public class CrashHookImpl2 implements Thread.UncaughtExceptionHandler, CrashHook {
private static volatile CrashHookImpl2 instance = null; private Thread.UncaughtExceptionHandler mSystemUeh; private Thread.UncaughtExceptionHandler mOtherUeh; private List<CutOffExceptionHandler> exceptionHandlers; private CrashHookImpl2() {
exceptionHandlers = new ArrayList<>(); } @Override public void hook() {
Thread.UncaughtExceptionHandler ueh = Thread.getDefaultUncaughtExceptionHandler(); if (ueh == null) {
mSystemUeh = null; mOtherUeh = null; Thread.setDefaultUncaughtExceptionHandler(CrashHookImpl2.this); return; } String androidUeh = "com.android.internal.os.RuntimeInit$UncaughtHandler"; String selfUeh = getClass().getName(); String currUeh = ueh.getClass().getName(); //系统的 if (androidUeh.equals(currUeh)) {
mSystemUeh = ueh; mOtherUeh = null; Thread.setDefaultUncaughtExceptionHandler(CrashHookImpl2.this); } else if (selfUeh.equals(currUeh)) {
//自己人 不处理 } else {
// bugly的 -> currUeh.contains("com.tencent.bugly.crashreport.crash") mSystemUeh = null; mOtherUeh = ueh; Thread.setDefaultUncaughtExceptionHandler(CrashHookImpl2.this); } return; } public static CrashHookImpl2 getInstance() {
if (instance == null) {
synchronized (CrashHookImpl2.class) {
if (instance == null) {
instance = new CrashHookImpl2(); } } } return instance; } @Override public void unHook() {
if (mSystemUeh != null) {
Thread.setDefaultUncaughtExceptionHandler(mSystemUeh); return; } if (mOtherUeh != null) {
Thread.setDefaultUncaughtExceptionHandler(mSystemUeh); return; } Thread.setDefaultUncaughtExceptionHandler(null); return; } @Override public void addCutOffExceptionHandler(CrashHook.CutOffExceptionHandler cutOffExceptionHandler) {
if (cutOffExceptionHandler == null) {
return; } exceptionHandlers.add(cutOffExceptionHandler); } @Override public void removeCutOffExceptionHandler(CrashHook.CutOffExceptionHandler cutOffExceptionHandler) {
if (cutOffExceptionHandler == null) {
return; } exceptionHandlers.remove(cutOffExceptionHandler); } public void tryHook(final long time) {
if (time < 0) {
return; } final HandlerThread thread = new HandlerThread("hook_ch"); thread.start(); final Handler handler = new Handler(thread.getLooper()); handler.post(new Runnable() {
private int size = 0; @Override public void run() {
if (size <= (time / 200)) {
size++; hook(); handler.postDelayed(this, 200); } else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
thread.quitSafely(); } else {
thread.quit(); } } } }); return; } @Override public void uncaughtException(Thread t, Throwable e) {
for (int i = 0; i < exceptionHandlers.size(); i++) {
boolean consumed = exceptionHandlers.get(i).onCutOffException(t, e); if (consumed) {
return; } } if (mOtherUeh != null) {
mOtherUeh.uncaughtException(t, e); } if (mSystemUeh != null) {
mSystemUeh.uncaughtException(t, e); } } }
代理 Thread.UncaughtExceptionHandler 的方式
实际上也是Hook默认的 Thread.UncaughtExceptionHandler , 但这种方式的好处是,我们自己无需创建实现Thread.UncaughtExceptionHandler接口的实现类,而只需要使用Proxy.newProxyInstance代理系统默认的Thread.UncaughtExceptionHandler就好了,这种方式比起上面一种来说,除了效果一致以外,好处可能就是可以避免一些代码的检查.
代理方式的hook代码:
public void hook() {
if (hooked) {
return; } Thread.UncaughtExceptionHandler ueh = Thread.getDefaultUncaughtExceptionHandler(); if (ueh == null) {
return; } //代理逻辑 class Px implements InvocationHandler {
private Thread.UncaughtExceptionHandler handler; private Method uncaughtExceptionMethod; private Px(Thread.UncaughtExceptionHandler handler) {
this.handler = handler; try {
uncaughtExceptionMethod = Thread.UncaughtExceptionHandler.class.getMethod("uncaughtException", Thread.class, Throwable.class); } catch (Throwable e) {
} } @Override public Object invoke(Object proxy, Method method, Object[] args) {
//先走自己的 try {
if (uncaughtExceptionMethod != null && uncaughtExceptionMethod.equals(method)) {
if (args != null && args.length == 2) {
Thread thread = (Thread) args[0]; Throwable throwable = (Throwable) args[1]; for (int i = 0; i < exceptionHandlers.size(); i++) {
boolean cutoff = exceptionHandlers.get(i).onCutOffException(thread, throwable); if (cutoff) {
//截断 return null; } } } } } catch (Throwable ignored) {
} try {
//原来的 method.invoke(handler, args); } catch (Throwable ignored) {
} return null; } } Thread.UncaughtExceptionHandler hookedUeh = (Thread.UncaughtExceptionHandler) Proxy.newProxyInstance( ueh.getClass().getClassLoader(), ueh.getClass().getInterfaces(), new Px(ueh)); Thread.setDefaultUncaughtExceptionHandler(hookedUeh); hooked = true; }
本种方式的全部实现代码:
讯享网 import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.List; public class CrashHookImpl implements CrashHook {
private List<CutOffExceptionHandler> exceptionHandlers; private static volatile CrashHookImpl instance = null; private boolean hooked = false; private CrashHookImpl() {
exceptionHandlers = new ArrayList<>(); } public static CrashHookImpl getInstance() {
if (instance == null) {
synchronized (CrashHookImpl.class) {
if (instance == null) {
instance = new CrashHookImpl(); } } } return instance; } @Override public void hook() {
if (hooked) {
return; } Thread.UncaughtExceptionHandler ueh = Thread.getDefaultUncaughtExceptionHandler(); if (ueh == null) {
return; } class Px implements InvocationHandler {
private Thread.UncaughtExceptionHandler handler; private Method uncaughtExceptionMethod; private Px(Thread.UncaughtExceptionHandler handler) {
this.handler = handler; try {
uncaughtExceptionMethod = Thread.UncaughtExceptionHandler.class.getMethod("uncaughtException", Thread.class, Throwable.class); } catch (Throwable e) {
} } @Override public Object invoke(Object proxy, Method method, Object[] args) {
try {
if (uncaughtExceptionMethod != null && uncaughtExceptionMethod.equals(method)) {
if (args != null && args.length == 2) {
Thread thread = (Thread) args[0]; Throwable throwable = (Throwable) args[1]; for (int i = 0; i < exceptionHandlers.size(); i++) {
boolean cutoff = exceptionHandlers.get(i).onCutOffException(thread, throwable); if (cutoff) {
//截断 return null; } } } } } catch (Throwable ignored) {
} try {
//原来的 method.invoke(handler, args); } catch (Throwable ignored) {
} return null; } } Thread.UncaughtExceptionHandler hookedUeh = (Thread.UncaughtExceptionHandler) Proxy.newProxyInstance( ueh.getClass().getClassLoader(), ueh.getClass().getInterfaces(), new Px(ueh)); Thread.setDefaultUncaughtExceptionHandler(hookedUeh); hooked = true; } @Override public void unHook() {
if (!hooked) {
return; } Thread.UncaughtExceptionHandler ueh = Thread.getDefaultUncaughtExceptionHandler(); if (ueh == null) {
return; } Thread.setDefaultUncaughtExceptionHandler(ueh); hooked = false; } @Override public void addCutOffExceptionHandler(CutOffExceptionHandler cutOffExceptionHandler) {
if (cutOffExceptionHandler == null) {
return; } exceptionHandlers.add(cutOffExceptionHandler); } @Override public void removeCutOffExceptionHandler(CutOffExceptionHandler cutOffExceptionHandler) {
if (cutOffExceptionHandler == null) {
return; } exceptionHandlers.remove(cutOffExceptionHandler); } }
结语
CrashHookImpl.getInstance().hook(); //保护所有的除零崩溃 CrashHookImpl.getInstance().addCutOffExceptionHandler(new CrashHook.CutOffExceptionHandler() {
@Override public boolean onCutOffException(Thread t, Throwable e) {
if (e.getClass().getName().equals("java.lang.ArithmeticException")) {
//返回true,截断崩溃 return true; } return false; } }); //统计上报 CrashHookImpl.getInstance().addCutOffExceptionHandler(new CrashHook.CutOffExceptionHandler() {
@Override public boolean onCutOffException(Thread t, Throwable e) {
StackTraceElement[] elements = e.getStackTrace(); for (int i = 0; i < elements.length; i++) {
String msg= elements[i].getClassName()+elements[i].getMethodName()+elements[i].getLineNumber(); //上报错误 } //返回false 不截断 return false; } });

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/48383.html