Android 项目中依赖项使用项目代码,出现 NoSuchMethodException - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
ntdll
V2EX    Java

Android 项目中依赖项使用项目代码,出现 NoSuchMethodException

  •  
  •   ntdll Nov 10, 2017 2261 views
    This topic created in 3090 days ago, the information mentioned may be changed or developed.

    其实算是一个比较诡异的需求,但是 leader 交代的,没办法。

    情况

    有一个普通的 jar 文件(无源码),要求在 Android 上运行,由于这个 jar 有部分方法调用在 Android 上不存在,因此我新建了一个 Android 工程,将这个 jar 作为依赖项引用到项目中。

    我在项目中写了该 jar 需要调用的一些方法,转换成了 Android 中存在的操作。随后编译,lint 不通过,当时没注意,随后忽略 lint 报告,直接打包,丢到设备上运行。

    设备上程序闪退,通过 logcat 发现,抛出了NoSuchMethodException,位置就在 jar 中调用 Android 中不存在的方法(该方法已经由我在项目中提供了)。随后查看之前的 lint 报告,说 jar 文件中引用的包不存在(即 Android 中不存在,但是已经在我项目中,我重写的)

    所以说,第三方 jar 作为 classpath,是不可以使用主程序的代码?但是将程序打包后,第三方 jar 与主程序位于同样的 classpath 下,由同一个 Classloader 加载( Android 中即 PathDexClassLoader ),按理说,不应该出现这样的情况呀。

    所以这种情况下,我可以如何做呢?

    7 replies    2017-11-11 21:22:00 +08:00
    nicevar
        1
    nicevar  
       Nov 10, 2017
    既然抛出了这个异常那就说明你打得包中是不存在这个方法,前面你说的一堆我看的不太明白,不过我觉得你的分析有问题,你应该把 apk 的 dex 拿出来检查一下是否存在这个方法,或者检查打包编译的中间文件,另外我很好奇既然原来的 jar 没有这些方法,你直接补做异常不行吗?还是说你必须要实现这些不存在的方法程序才能正常?
    ntdll
        2
    ntdll  
    OP
       Nov 10, 2017
    @nicevar 反编译查看过,最终文件中是存在的。这样说吧,原来的项目是 A -> B -> J2SE Platform,依次依赖;现在变成 A -> D -> Android Platform。其中 D 就是我现在写的 Android 项目,A 就是那个 jar 文件。原来的依赖路径中有部分方法,在 Android 中并不存在,因此为了让 A 能够顺利在 Android 中启动,我写了 D 项目,将原本 Android 中不存在的方法补上,转成 Android 支持的方法。

    那么现在的情况就是,编译是可以顺利通过的。但是运行期间,A 中的调用我在 D 中写的方法,会提示方法不存在。
    AckywOw
        3
    AckywOw  
       Nov 10, 2017
    表示完全晕了,看不懂到底 @@情况...
    eminemcola
        4
    eminemcola  
       Nov 10, 2017
    @gam2046 我猜 jar 中所调用的这个 Java 方法所在的包路径是显式 import 的,在这个路径下可能搜索不到你写在 D 里面的替代方案。可以尝试 catch 一下这个 exception。
    jameslan
        5
    jameslan  
       Nov 11, 2017 via Android
    他的 classloader 出于某种原因不去找你的 mock。试试抢先把 mock load 进来?

    但是这么 risky 的解决方案真的要用么。。。。
    ntdll
        6
    ntdll  
    OP
       Nov 11, 2017
    @eminemcola catch 到这个异常以后呢,并没有什么方法处理,原方法的参数我也拿不到,也无法恢复。

    @jameslan 按理来说,在 Android 上整个 apk 都是由同一个 PathDexClassLoader 加载,不应该存在这种情况。而且我单步调试过,发现 BootClassLoader 与 PathDexClassLoader 正常,且在调试模式下,IDE 注入的进程是可以正常调用这个方法,只是程序自身无法调用会出现 NoSuchMethodException。至今不理解。
    nicevar
        7
    nicevar  
       Nov 11, 2017
    @gam2046 你确定那个报异常的方法存在?我指的不是类文件,你这种方案类似的我在好几年前还是 2.3 系统的时候做过,是可行的,现在你描述的情况是 class 明显没有加载进去,另外你分析一下 davlik-cache 生成的 dex 看看
    还有种情况,系统之前是否加载过没有这个方法的类,如果有加载过而且改应用是系统应用并且 persistent 是 true,这样就会触发系统的一个 bug,更新了程序内存里面依然加载的是以前的 class,需要断电重启一次
    About     Help     Advertise     Blog     API     FAQ     Solana     5761 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 97ms UTC 01:43 PVG 09:43 LAX 18:43 JFK 21:43
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86