记一次混淆后引起的异常,被覆盖的方法未抛出Exception

前言

本地开发的时候运行正常,开启了混淆之后编译通过运行失败

描述

项目中遇到了一个问题,module中有一个方法,改方法会抛Exception,

    public Map<String, String> encryptParams(Map<String, String> params) throws Exception {
        return params;
    }

在主工程中有一个改类的子类复写类该方法,做了一些其他的逻辑,开发的时候为类方便把混淆关了直接关联工程开发。调试完毕之后开了混淆准备打包然后就build 失败。

0001

根据提示判断是因为父类中的encryptParams()方法未抛Exception,所以子类也不能抛。看代码确定是有throw Exception的,于是Module打出来的jar反编译下看看到底有没有。

JD-GUI可以很方便的反编译jar包。使用AndroidStudio更方便直接把jar拖到libs下面,然后sync。

记一次混淆后引起的异常,被覆盖的方法未抛出Exception_第1张图片

可以看到混淆后的代码

0003

来一张对比的

记一次混淆后引起的异常,被覆盖的方法未抛出Exception_第2张图片

对比发现混淆后的jar是没有throw Exception的,这里的gradle版本是1.5.0,仔细观察发现map的泛型也没有。

再来一张gradle 2.3.3 版本的(因为我Studio版本是2.3.3的),有泛型没有throw Exception

记一次混淆后引起的异常,被覆盖的方法未抛出Exception_第3张图片

最后放上三个对比的

//    混淆后 gradle 1.5.0
//    public Map encryptParams(Map var1) {
//        return var1;
//    }

//    混淆后 gradle 2.3.3
//    public Map encryptParams(Map var1) {
//        return var1;
//    }

    //混淆前
    public Map<String, String> encryptParams(Map<String, String> params) throws Exception {
        return params;
    }

Demo地址

结论

gradle 1.5.0版本 在开启混淆生成jar的时候会把泛型和throw Exception去掉,gradle 2.3.3版本开启有泛型无throw Exception。原因暂未查到,有清楚的欢迎讨论。

补充

后期发现泛型是因为没有在混淆配置中添加忽略,添加以下内容就可以保留混淆。

# 避免混淆泛型
-keepattributes Signature

最终解决方案

今天突然想起来,EventBus在注册了两次之后会抛异常,就去看下EventBus怎么处理的。直接看代码

    // Must be called in synchronized block
    private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
       ...
        if (subscriptions == null) {
            subscriptions = new CopyOnWriteArrayList<>();
            subscriptionsByEventType.put(eventType, subscriptions);
        } else {
            if (subscriptions.contains(newSubscription)) {
                throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
                        + eventType);
            }
        }
        ...

抛了异常但方法上没有throws ,跟进去EventBusException

public class EventBusException extends RuntimeException { ... }

原来如此。
方法来了,只需要把我们之前的Exception 换成 RuntimeException或者自定义一个他的子类就可以解决库中抛的异常不会打进jar中的问题了,然后在需要的地方处理catch到的异常。
Exception:在程序中必须使用try…catch进行处理。
RuntimeException:可以不使用try…catch进行处理,但是如果有异常产生,则异常将由JVM进行处理。
所以,为了保证程序再出错后依然可以执行,在开发代码时最好使用try…catch的异常处理机制进行处理。

你可能感兴趣的:(遇到的问题)