Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

java.lang.UnsatisfiedLinkError Native method not found #334

Closed
JackyAndroid opened this issue Dec 6, 2017 · 44 comments
Closed

java.lang.UnsatisfiedLinkError Native method not found #334

JackyAndroid opened this issue Dec 6, 2017 · 44 comments

Comments

@JackyAndroid
Copy link

JackyAndroid commented Dec 6, 2017

因为xlog崩溃导致产品不能上线,希望作者能尽快回复,多谢。

  1. 项目中第三方库包含stlport_shared so库
  2. 混淆配置:
    -keep class com.tencent.mars.** {
    public protected private *;
    }
    堆栈信息如下:
    Caused by:
    java.lang.UnsatisfiedLinkError:Native method not found: com.tencent.mars.xlog.Xlog.logWrite2:(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;IIJJLjava/lang/String;)V
    com.tencent.mars.xlog.Xlog.logWrite2(Native Method)
    com.tencent.mars.xlog.Xlog.logD(Xlog.java:48)
    com.tencent.mars.xlog.Log.d(Log.java:264)
    com.tencent.mars.xlog.Log.d(Log.java:208)
@JackyAndroid
Copy link
Author

@garryyan
Copy link
Collaborator

garryyan commented Dec 7, 2017

  1. 是否load了 xlog 的so
  2. 是否有修改过C++代码或者修改过xlog相关的native函数

@JackyAndroid
Copy link
Author

@garryyan

  1. 流程肯定是走了,但是Java层如何准确判断成功加载so呢?加上如下一个标记可以吗?
    try {
    System.loadLibrary("stlport_shared");
    System.loadLibrary("marsxlog");
    isInit = true;
    } catch (Exception e) {
    isInit = false;
    e.printStackTrace();
    }
  2. 没有修改过so代码,只是通过源码编译为v7版本,使用ndk-r11版本

@garryyan
Copy link
Collaborator

garryyan commented Dec 7, 2017

查看下logcat 有没有load so的日志。
你的程序是单进程的?还是多进程的?

@JackyAndroid
Copy link
Author

@garryyan

  1. 这些崩溃是灰度版本bugly统计上来的,我这边并不能复现,也没办法查看load so日志。
  2. 程序是多进程的,但是保证只在主进程加载so

@garryyan
Copy link
Collaborator

garryyan commented Dec 7, 2017

  1. crash率是多少
  2. 其他进程会调用xlog吗

@JackyAndroid
Copy link
Author

  1. 一万灰度用户影响用户42,发生次数69
  2. 排查了下,其他进程应该不会调用xlog

@garryyan
Copy link
Collaborator

garryyan commented Dec 7, 2017

之前遇到过类似的问题,是因为在安装的过程中,安装成功了,但是so没有copy过去。 能不能确认是否是这个问题

@JackyAndroid
Copy link
Author

@garryyan 这个确实很难确认,如果是这个问题,该如何解决呢?如果在主进程加载xlog so,在其他进程使用也会导致这个问题吗?

@garryyan
Copy link
Collaborator

garryyan commented Dec 7, 2017

可以启动的时候检测so,如果不对就自己copy过去一份。

如果主进程加载xlog,其他进程没加载但又调用,肯定会导致这个问题。所以看看你的crash发生在哪个进程

@JackyAndroid
Copy link
Author

@garryyan 我排查了下bugly 崩溃确认发生在主进程,除了“安装成功了,但是so没有copy过去”这种情况外,你还有其他的建议吗?

@garryyan
Copy link
Collaborator

garryyan commented Dec 7, 2017

没其他建议了,最好能找一个重现的用户确认下。

@JackyAndroid
Copy link
Author

@garryyan 如果是因为安装成功,但是so没有copy过去,出现的错误不应该是*.so not found么?为什么我这边的都是“Native method not found ”?

@JackyAndroid
Copy link
Author

目前我的做法是让日志模块初始化的时候检查下xlog so是不是存在,如果不存在都不会打印。
今晚会发一次灰度,明天再看下数据。

@JackyAndroid JackyAndroid changed the title 【紧急】java.lang.UnsatisfiedLinkError Native method not found java.lang.UnsatisfiedLinkError Native method not found Dec 9, 2017
@JackyAndroid
Copy link
Author

JackyAndroid commented Dec 9, 2017

@garryyan 目前在程序启动时候加了so检查,但是还是没办法解决Native method not found
异常设备信息如下,几乎所有的崩溃集中在Android 4.4 版本

image

堆栈如下:

1 java.lang.IllegalStateException:Fatal Exception thrown on Scheduler.Worker thread.

2 rx.internal.schedulers.ScheduledAction.void run()(ScheduledAction.java:59)
3 ......
4 java.lang.UnsatisfiedLinkError:Native method not found: com.tencent.mars.xlog.Xlog.logWrite2:(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;IIJJLjava/lang/String;)V
5 com.tencent.mars.xlog.Xlog.void logWrite2(int,java.lang.String,java.lang.String,java.lang.String,int,int,long,long,java.lang.String)(Native Method)
6 com.tencent.mars.xlog.Xlog.void logI(java.lang.String,java.lang.String,java.lang.String,int,int,long,long,java.lang.String)(Xlog.java:53)
7 com.tencent.mars.xlog.Log.void i(java.lang.String,java.lang.String,java.lang.Object[])(Log.java:254)
8 com.tencent.mars.xlog.Log.void i(java.lang.String,java.lang.String)(Log.java:198)
有没有解决思路?

@garryyan
Copy link
Collaborator

garryyan commented Dec 9, 2017

有没有可能调用xlog的接口早于so的加载

@JackyAndroid
Copy link
Author

@garryyan 我做了判断的,初始化失败是不会调用的。

image

@garryyan
Copy link
Collaborator

garryyan commented Dec 9, 2017

看不出来,试着找相关机器重现下。

@fengshenzhu
Copy link

Bugly反馈相同error,但是Crash栈不一样:

#1 main
java.lang.UnsatisfiedLinkError
Native method not found: com.tencent.mars.stn.StnLogic.setLonglinkSvrAddr:(Ljava/lang/String;[ILjava/lang/String;)V
解析原始
1 com.tencent.mars.stn.StnLogic.setLonglinkSvrAddr(Native Method)
2 com.tencent.mars.stn.StnLogic.setLonglinkSvrAddr(StnLogic.java:286)
...

只有Android 4.4.4,level 19出现

@yuhui2016github
Copy link

线上5.0以下的手机也是出现大量类似的崩溃:
java.lang.UnsatisfiedLinkError: Native method not found: com.tencent.mars.BaseEvent.onNetworkChange:()V
at com.tencent.mars.BaseEvent.onNetworkChange(Native Method)
at com.tencent.mars.BaseEvent$ConnectionReceiver.checkConnInfo(BaseEvent.java:70)
at com.tencent.mars.BaseEvent$ConnectionReceiver.onReceive(BaseEvent.java:51)
at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:782)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5336)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:871)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:687)
at dalvik.system.NativeStart.main(Native Method)

请问微信这边有遇到过吗? @garryyan 会不会和linearAlloc有关,目前都只有5.0以下手机有这个问题,5.0及以上没有报过

@garryyan garryyan reopened this Apr 8, 2018
@garryyan
Copy link
Collaborator

garryyan commented Apr 8, 2018

@yuhui2016github 已经保证了在调用onNetworkChange 之前已经load了so了吗?

@garryyan
Copy link
Collaborator

garryyan commented Apr 8, 2018

@yuhui2016github 还有

  1. load so 的线程是主线程,还是其他线程?
  2. 如果load so的线程是其他线程,是否存在多个线程同时load 不同的 so?

@yuhui2016github
Copy link

@garryyan
已经保证在调用onNetworkChange 之前已经load了so,这个问题是非必现的,我们的QA试过遇到2次,从QA提供的日志来看,加载so的时候没有遇到异常。而且onNetworkChange也不是第一个调用的native方法,如果是因为so没有load的话,应该在调用BaseEvent.onCreate()时就会抛出异常了。我们有点怀疑是和linearAlloc限制有关。微信使用mars的时候,完全没有这个崩溃?

1.load so 的线程是主线程,还是其他线程?
是在主线程

@garryyan
Copy link
Collaborator

garryyan commented Apr 8, 2018

我们之前也是没有这个错误的,最近业务改造也开始出现了这个错误。 不过怀疑是在子线程多线程load so导致的问题,和你的不是同一类问题。我们的也在排查中

@garryyan
Copy link
Collaborator

@yuhui2016github 我们自己发现如果调用的哪个函数出现这个异常,try catch住再次调用这个函数,这个异常就没了。 按照道理来讲, 如果真的有问题,catch住再次调用这个函数还会抛出来异常才对。 具体原因还需要探索

@yuhui2016github
Copy link

@garryyan 你们的问题确定是多线程导致的么? 如果是多线程导致的,那会不会可能是在‘’catch住再次调用”时,load so刚好完成了,所以第二次调用的时候没问题。

你们出现的崩溃都是在5.0以下的手机上出现吗?
我们那个出现在5.0以下手机的崩溃,你们没出现,可能是你们微信已经做了LinearAlloc的优化

@garryyan
Copy link
Collaborator

我们只是猜测是多线程导致的,但是 调用函数和load so其实是发生在一个线程的,而且保证了先后顺序。所以目前只是说可能其他的机制导致的。

我们出现都是android-19。 建议你们也尝试下我们的修复方式,看量会不会减少。

@yuhui2016github
Copy link

yuhui2016github commented Apr 19, 2018

@garryyan 请问你们有发现是什么原因导致的吗?我们这边一开始认为可能是LinearAlloc缓冲不够大导致的,于是我们把Dalvik的LinearAlloc改大(由16m增大至32m),可是依然会出现这个崩溃。现在在试一下你们的修复方式看看量会不会减少

@garryyan 现在试了“如果调用的哪个函数出现这个异常,try catch住再次调用这个函数”这个修复方式,新的版本线上确实没发现这个崩溃了,具体原因现在还没有很好的结论。

@liungkejin
Copy link

刚好我们项目最近也遇到了这种问题,所以我来插一句 😄
多线程的问题我们已经试过了,并没有解决问题,看log 大部分出现在第一次使用 native 方法报错,也有一部分是中间的一个固定的方法(这点很奇怪,每次错误都是固定的方法),我找到了一篇文章希望对你们有帮助 https://www.jianshu.com/p/fbd3820d0864

我们下一步准备试一下 catch 住异常,然后重新 load .so 的方法

@HTonny
Copy link

HTonny commented Apr 26, 2018

你好,我们项目最近用,有个这个崩溃,不知咋回事,在android 4.4.4的系统上有这样的崩溃:
W/dalvikvm: Invalid indirect reference 0x426a1588 in decodeIndirectRef
I/dalvikvm: "main" prio=5 tid=1 RUNNABLE
I/dalvikvm: | group="main" sCount=0 dsCount=0 obj=0x417bdf00 self=0x416d7788
I/dalvikvm: | sysTid=11307 nice=0 sched=0/0 cgrp=apps handle=1073996116
I/dalvikvm: | state=R schedstat=( 1863453124 109119266 11240 ) utm=127 stm=59 core=2
I/dalvikvm: at com.tencent.mars.BaseEvent.onCreate(Native Method)
I/dalvikvm: at com.tencent.mars.BaseEvent.onCreate(Native Method)
I/dalvikvm: at com.tencent.mars.a.a(Mars.java:44)

@HTonny
Copy link

HTonny commented Apr 27, 2018

这个奔溃我们再观察下

@liungkejin
Copy link

我们测试了 catch 住这个错误,重新 load .so 的方法是可行的,基本可以避免 90% 以上的问题

@bravekingzhang
Copy link

@zhlila
Copy link

zhlila commented Oct 12, 2018

这个帖子已经是我找到的最详细描述 Android 4.x 加载so 偶现java.lang.UnsatisfiedLinkError Native method not found错误的帖子了。

这个问题确实很棘手,而且不清楚原因是什么:
1.手工不能复现,但是bugly后台上报量却不少。
2.bugly后台上报统计的人均crash次数不多,可见即便是发生过错误的用户,也只是偶见,并不保证一定必现。
3.如同楼上的答主所言,native的方法很多,但是上报回来的crash地方 却往往都是固定的那一两个地方。
4.我的应用加载了很多so,但是会上报crash的so,就这一个。(这一点也似乎说明,可能就是那个so有问题)

我准备试试楼上答主说的catch住再重复加载和调用的解决办法。。
也希望能有大神能从根本上找到原因解决这个问题。。

@JackyAndroid
Copy link
Author

这个问题微信已经解决了?方案是什么

@garryyan
Copy link
Collaborator

@yuhui2016github 我们自己发现如果调用的哪个函数出现这个异常,try catch住再次调用这个函数,这个异常就没了。 按照道理来讲, 如果真的有问题,catch住再次调用这个函数还会抛出来异常才对。 具体原因还需要探索

我们目前采用的这个方式

@elviswoo
Copy link
Contributor

elviswoo commented Nov 21, 2018

这个帖子已经是我找到的最详细描述 Android 4.x 加载so 偶现java.lang.UnsatisfiedLinkError Native method not found错误的帖子了。

这个问题确实很棘手,而且不清楚原因是什么:
1.手工不能复现,但是bugly后台上报量却不少。
2.bugly后台上报统计的人均crash次数不多,可见即便是发生过错误的用户,也只是偶见,并不保证一定必现。
3.如同楼上的答主所言,native的方法很多,但是上报回来的crash地方 却往往都是固定的那一两个地方。
4.我的应用加载了很多so,但是会上报crash的so,就这一个。(这一点也似乎说明,可能就是那个so有问题)

我准备试试楼上答主说的catch住再重复加载和调用的解决办法。。
也希望能有大神能从根本上找到原因解决这个问题。。

这个问题的本质原因是dalvik实现的bug,5.0之后使用了art也就没有这个问题了。这个bug是这样的:
1)System.LoadLibary在dalvik的最终实现是在android/dalvik/vm/Native.cpp这个文件里面通过dlopen去打开一个so,并存放一些so相关信息到一个全局hashtable里面去
2)java通过jni调用native函数的最终实现也是在android/dalvik/vm/Native.cpp这个文件里面,通过遍历这个hashtable,和dlsym函数,找到这个native函数的地址,进而调用它。
3)问题的关键是这个hashtable并不线程安全,当调用一个native函数时(遍历hashtable),此时另外一个线程在load任意一个其他so,这会改变hashtable的长度,进而导致遍历hashtable操作native符号失败。
4)由于这种多线程竞争情况的存在,在catch UnsatisfiedLinkError里面再调用一次native函数,一般就能避开多线程竞争

@zhlila
Copy link

zhlila commented Nov 29, 2018

@elviswoo 我看了下源码,确实操作hashtable没有加锁。如果在查找方法的时候,恰巧另外一个线程在做load so导致触发hashtable扩容的时候,的确是有可能导致native method not found。不过,如果是这样的话,那应该是不需要重新加载so的。应该是只需要重新调用一次那个方法即可。我验证一下是不是可以让bugly的上报减少。

@linguokun1
Copy link

@stcdalyc 这个有结果吗 最后是如何解决的呢

@zhlila
Copy link

zhlila commented Mar 1, 2019

@stcdalyc 这个有结果吗 最后是如何解决的呢

重新调用一次那个方法即可,确实可以减少大部分的上报。

@linguokun1
Copy link

@stcdalyc 谢谢

@tinggengyan
Copy link

@yuhui2016github 我们自己发现如果调用的哪个函数出现这个异常,try catch住再次调用这个函数,这个异常就没了。 按照道理来讲, 如果真的有问题,catch住再次调用这个函数还会抛出来异常才对。 具体原因还需要探索

我们目前采用的这个方式

这个报错是个error,会直接导致crash,请问怎么做到再调用一次的呢? @garryyan

@garryyan
Copy link
Collaborator

garryyan commented Apr 3, 2019

@yuhui2016github 我们自己发现如果调用的哪个函数出现这个异常,try catch住再次调用这个函数,这个异常就没了。 按照道理来讲, 如果真的有问题,catch住再次调用这个函数还会抛出来异常才对。 具体原因还需要探索

我们目前采用的这个方式

这个报错是个error,会直接导致crash,请问怎么做到再调用一次的呢? @garryyan

try {
// your code
} catch(Throwable t) {
// your code again
}

@garryyan garryyan pinned this issue Apr 3, 2019
@tinggengyan
Copy link

@yuhui2016github 我们自己发现如果调用的哪个函数出现这个异常,try catch住再次调用这个函数,这个异常就没了。 按照道理来讲, 如果真的有问题,catch住再次调用这个函数还会抛出来异常才对。 具体原因还需要探索

我们目前采用的这个方式

这个报错是个error,会直接导致crash,请问怎么做到再调用一次的呢? @garryyan

try {
// your code
} catch(Throwable t) {
// your code again
}

Thank you !!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests