java.lang.ExceptionInInitializerError原因及解决办法

java.lang.Object
java.lang.Throwable
java.lang.Error
java.lang.LinkageError
java.lang.ExceptionInInitializerError

ExceptionInInitializerError 通常意味着在静态初始化块或静态变量初始化过程中发生了异常。

静态代码块异常:如果在静态代码块中有任何异常抛出,都会导致此错误。

1
2
3
4
5
6
7
8
public class StaticBlock {

private static int state;

static {
state = 42 / 0; //除0异常
}
}

静态变量初始化异常:如果静态变量在初始化时抛出了异常,也会导致此错误。(编译后实际上也是在静态代码块里面)

1
2
3
4
public class Example {
private static final int number = Integer.parseInt("abc"); // 这里会抛出NumberFormatException
}

解决方法

一般来说,查看堆栈跟踪都能找出问题所在。

  1. 检查静态初始化块:确保静态初始化块中没有抛出异常的代码。
  2. 检查静态变量初始化:确保所有静态变量的初始化都是安全的,没有抛出异常。

工作中的例子

1
java.lang.ExceptionInInitializerError at com.xxx.xx.Service.onInit(Service.java:654) 

查看654行代码,引用了一个静态类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
static {
try {
String path = "/data/data/com.xxx.xx/lib/libxxplay.so";
File file = new File(path);
if (file.exists()) {
SFLogger.d(TAG, "use /data/data/com.xxx.xx/lib/libxxplay.so");
System.load(path);
} else {
SFLogger.d(TAG, "use /system/lib/libxxplay.so");
System.loadLibrary("xxplay");
}
} catch (Exception e) {
SFLogger.e(TAG, "JniUtil loadLibrary exception = " + e.getMessage());
}
}

以上代码咋一看好像也没什么问题啊,异常都catch住了。

但如果仔细研究就会发现,这里的问题是滥用了Exception,没有针对具体异常进行捕获。查看loadLibrary源码发现其可能会抛出SecurityExceptionUnsatisfiedLinkError或者NullPointerExceptionSecurityExceptionNullPointerException的父类都是RuntimeException,是一种异常(Exception),UnsatisfiedLinkError的父类是LinkageError,是一种错误(Error),所以如果这里发生了UnsatisfiedLinkError,通过Exception是捕获不了的,必须通过他们的共同父类Throwable来进行捕获。当然,最好还是针对具体的异常进行捕获,不要用这种扩大化的捕获方式,容易隐藏问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
* Loads the native library specified by the <code>libname</code>
* argument. The <code>libname</code> argument must not contain any platform
* specific prefix, file extension or path. If a native library
* called <code>libname</code> is statically linked with the VM, then the
* JNI_OnLoad_<code>libname</code> function exported by the library is invoked.
* See the JNI Specification for more details.
*
* Otherwise, the libname argument is loaded from a system library
* location and mapped to a native library image in an implementation-
* dependent manner.
* <p>
* The call <code>System.loadLibrary(name)</code> is effectively
* equivalent to the call
* <blockquote><pre>
* Runtime.getRuntime().loadLibrary(name)
* </pre></blockquote>
*
* @param libname the name of the library.
* @exception SecurityException if a security manager exists and its
* <code>checkLink</code> method doesn't allow
* loading of the specified dynamic library
* @exception UnsatisfiedLinkError if either the libname argument
* contains a file path, the native library is not statically
* linked with the VM, or the library cannot be mapped to a
* native library image by the host system.
* @exception NullPointerException if <code>libname</code> is
* <code>null</code>
* @see java.lang.Runtime#loadLibrary(java.lang.String)
* @see java.lang.SecurityManager#checkLink(java.lang.String)
*/
@CallerSensitive
public static void loadLibrary(String libname) {
Runtime.getRuntime().loadLibrary0(Reflection.getCallerClass(), libname);
}

参考

ExceptionInInitializerError | Android Developers

When Does Java Throw the ExceptionInInitializerError? | Baeldung

Chapter 11. Exceptions


java.lang.ExceptionInInitializerError原因及解决办法
https://iwesley.top/article/78c113a2/
作者
Wesley
发布于
2024年6月2日
许可协议