Android 项目开发填坑记 - NoSuchMethodError:(java.lang.System.arraycopy)

关键字:NoSuchMethodErrorSystem.arraycopyNative Method

0x00:奇怪的异常

应用新版本上线后观察错误日志,发现一个奇怪的 Crash 异常信息:

1
lang.java.NoSuchMethodError: (java.lang.System.arraycopy)

异常集中发生在 Android 4.4.2 和 Android 5.1 上面,System.arraycopy() 是一个系统函数,要说没这个方法倒是不会,但异常发生了,说明应用在找这个方法时发生了错误。

0x01:探究原因

根据异常日志,追踪到 System.arraycopy()Base64.javapublic static byte[] decode(byte[] source, int off, int len, int options) 方法里调用的。

经过查找 Android API 19~21 的系统源码,发现发生此问题的原因是 Android>=21 时,java.lang.System.arraycopy() 多了几个重载。

在 Android <=20 上:

1
2
//java.lang.System 只有一个 arraycopy 方法
public static native void arraycopy(Object src, int srcPos,Object dst, int dstPos, int length);

在 Android >=21 上:

1
2
3
4
5
6
7
8
//java.lang.System
public static native void arraycopy(Object src, int srcPos,Object dst, int dstPos, int length);
/**
* The byte[] specialized version of arraycopy().
*
* @hide internal use only
*/
public static void arraycopy(byte[] src, int srcPos, byte[] dst, int dstPos, int length){}

Base64.java 应该使用的是 native void arraycopy(Object src... ,但是会在 compileSdkVersion>=21 时使用重载的 arraycopy(byte[] src … ,那么运行在 Android <=20 的手机上时就会报 java.lang.NoSuchMethodError 的异常了。

总结下来就是:如果你在 Android 上使用了此 Base64 工具类,并且编译时使用的 Android 版本>=21,那么在低版本上你可能会遇到 java.lang.NoSuchMethodError: java.lang.System.arraycopy 的异常。之所以说是可能,是因为出现此异常时在开发平常的应用时不会发生,一般是使用修改后的系统 Jar 包调用系统隐藏方法时才容易出现。

0x02:解决方案

如何解决呢?有两个方法:

1.指定使用 arraycopy 使用的重载方法,避免编译器用错

1
2
3
System.arraycopy(outBuff, 0, out, 0, outBuffPosn);
//替换成
System.arraycopy((Object) outBuff, 0, (Object) out, 0, outBuffPosn);

2.使用 Arrays.copyOf () 来替代 System.arraycopy()

1
2
3
System.arraycopy(outBuff, 0, out, 0, outBuffPosn);
//替换成
out = Arrays.copyOf(outBuff, outBuffPosn);

虽然 Arrays.copyOf() 的方法实现最后还是调用的 System.arraycopy() ,但是不会调用到错误的重载方法。

PS:你可以通过下面的方式和我联系