Jasypt无法在Android 5.1.1及更高版本上初始化,ClassLoader为null

时间:2016-02-08 16:49:51

标签: android nullpointerexception classloader jasypt

我正常使用Jasypt(compile 'org.jasypt:jasypt:1.9.2')和标准PBE加密器

    StandardPBEByteEncryptor strongBinaryEncryptor = new StandardPBEByteEncryptor();
    strongBinaryEncryptor.setAlgorithm("...");
    strongBinaryEncryptor.setKeyObtentionIterations(...);
    strongBinaryEncryptor.setProviderName(BouncyCastleProvider.PROVIDER_NAME);
    strongBinaryEncryptor.setPassword("...");
    byte[] encryptedBytes = strongBinaryEncryptor.encrypt(bytes);

这曾经没有问题,但现在它崩溃了以下根异常:

E/AndroidRuntime:  Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String)' on a null object reference
E/AndroidRuntime:     at org.jasypt.normalization.Normalizer.initializeIcu4j(Normalizer.java:139)
E/AndroidRuntime:     at org.jasypt.normalization.Normalizer.normalizeToNfc(Normalizer.java:96)
E/AndroidRuntime:     at org.jasypt.encryption.pbe.StandardPBEByteEncryptor.initialize(StandardPBEByteEncryptor.java:661)
E/AndroidRuntime:     at org.jasypt.encryption.pbe.StandardPBEByteEncryptor.encrypt(StandardPBEByteEncryptor.java:873) 

相同的代码适用于Kitkat手机和Lollipop模拟器,但例如在OnePlusOne上崩溃。

如果你看看来源,你看到的是:

static void initializeIcu4j() throws ClassNotFoundException {        
    Thread.currentThread().getContextClassLoader().loadClass(ICU_NORMALIZER_CLASS_NAME);
    useIcuNormalizer = Boolean.TRUE;
}

这意味着Thread.currentThread().getContextClassLoader()null。这并没有发生,我真的不知道是什么导致了这种行为的改变。我也不确定应该怎么做才能解决它。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

基于已经从Google Code中删除的wiki页面,这实际上曾经是Dalvik中的一个错误,但是在Froyo中提交了一个补丁。然而,ART似乎重新出现了这个完全相同的问题。

显然,根据https://web.archive.org/web/20120303234738/http://code.google.com/p/dalvik/wiki/JavaxPackages,解决方案是在Activity.onCreate()中手动初始化类加载器。

public class HelloStax extends Activity {
  @Override public void onCreate(Bundle savedInstanceState) {

    ...

    /*
     * Ensure the factory implementation is loaded from the application
     * classpath (which contains the implementation classes), rather than the
     * system classpath (which doesn't).
     */
    Thread.currentThread().setContextClassLoader(getClass().getClassLoader());

    ...
  }