powered by Jive Software

Smack 4.3.2 throws a java.lang.ExceptionInInitializerError exception on Android 9

I’m trying to create a chat application using smack on android. Recently when i checked crashlytics logs i discovered a strange error which is happening on Android 9 devices. Smack throws java.lang.ExceptionInInitializerError.

I’m using smack 4.3.2. It seems to work with other Android versions. This is the exception stack;

Caused by org.apache.commons.logging.LogConfigurationException: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.String.trim()' on a null object reference (Caused by java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.String.trim()' on a null object reference)
       at org.apache.commons.logging.impl.LogFactoryImpl.newInstance + 571(LogFactoryImpl.java:571)
       at org.apache.commons.logging.impl.LogFactoryImpl.getInstance + 292(LogFactoryImpl.java:292)
       at org.apache.commons.logging.impl.LogFactoryImpl.getInstance + 269(LogFactoryImpl.java:269)
       at org.apache.commons.logging.LogFactory.getLog + 655(LogFactory.java:655)
       at org.apache.http.conn.ssl.AbstractVerifier.(AbstractVerifier.java:2)
       at org.apache.http.conn.ssl.StrictHostnameVerifier.(StrictHostnameVerifier.java:1)
       at org.apache.http.conn.ssl.StrictHostnameVerifier.(StrictHostnameVerifier.java:1)
       at org.jivesoftware.smack.android.AndroidSmackInitializer.initialize + 41(AndroidSmackInitializer.java:41)
       at org.jivesoftware.smack.SmackInitialization.loadSmackClass + 212(SmackInitialization.java:212)
       at org.jivesoftware.smack.SmackInitialization.parseClassesToLoad + 173(SmackInitialization.java:173)
       at org.jivesoftware.smack.SmackInitialization.processConfigFile + 143(SmackInitialization.java:143)
       at org.jivesoftware.smack.SmackInitialization.processConfigFile + 128(SmackInitialization.java:128)
       at org.jivesoftware.smack.SmackInitialization.(SmackInitialization.java:12)
       at org.jivesoftware.smack.SmackConfiguration.getVersion + 93(SmackConfiguration.java:93)
       at org.jivesoftware.smack.ConnectionConfiguration.(ConnectionConfiguration.java:1)
       at org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration.builder + 80(XMPPTCPConnectionConfiguration.java:80)
       at com.davidoff.chat.ChatServiceConnection.createConnection + 234(ChatServiceConnection.java:234)
       at com.davidoff.chat.ChatServiceConnection.connect + 281(ChatServiceConnection.java:281)
       at com.davidoff.chat.ChatService.initConnection + 167(ChatService.java:167)
       at com.davidoff.chat.ChatService$1.run + 145(ChatService.java:145)
       at java.lang.Thread.run + 764(Thread.java:764)

Caused by java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.String.trim()' on a null object reference
       at org.apache.commons.logging.impl.LogFactoryImpl.createLogFromClass + 1067(LogFactoryImpl.java:1067)
       at org.apache.commons.logging.impl.LogFactoryImpl.discoverLogImplementation + 844(LogFactoryImpl.java:844)
       at org.apache.commons.logging.impl.LogFactoryImpl.newInstance + 541(LogFactoryImpl.java:541)
       at org.apache.commons.logging.impl.LogFactoryImpl.getInstance + 292(LogFactoryImpl.java:292)
       at org.apache.commons.logging.impl.LogFactoryImpl.getInstance + 269(LogFactoryImpl.java:269)
       at org.apache.commons.logging.LogFactory.getLog + 655(LogFactory.java:655)
       at org.apache.http.conn.ssl.AbstractVerifier.(AbstractVerifier.java:2)
       at org.apache.http.conn.ssl.StrictHostnameVerifier.(StrictHostnameVerifier.java:1)
       at org.apache.http.conn.ssl.StrictHostnameVerifier.(StrictHostnameVerifier.java:1)
       at org.jivesoftware.smack.android.AndroidSmackInitializer.initialize + 41(AndroidSmackInitializer.java:41)
       at org.jivesoftware.smack.SmackInitialization.loadSmackClass + 212(SmackInitialization.java:212)
       at org.jivesoftware.smack.SmackInitialization.parseClassesToLoad + 173(SmackInitialization.java:173)
       at org.jivesoftware.smack.SmackInitialization.processConfigFile + 143(SmackInitialization.java:143)
       at org.jivesoftware.smack.SmackInitialization.processConfigFile + 128(SmackInitialization.java:128)
       at org.jivesoftware.smack.SmackInitialization.(SmackInitialization.java:12)
       at org.jivesoftware.smack.SmackConfiguration.getVersion + 93(SmackConfiguration.java:93)
       at org.jivesoftware.smack.ConnectionConfiguration.(ConnectionConfiguration.java:1)
       at org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration.builder + 80(XMPPTCPConnectionConfiguration.java:80)
       at com.davidoff.chat.ChatServiceConnection.createConnection + 234(ChatServiceConnection.java:234)
       at com.davidoff.chat.ChatServiceConnection.connect + 281(ChatServiceConnection.java:281)
       at com.davidoff.chat.ChatService.initConnection + 167(ChatService.java:167)
       at com.davidoff.chat.ChatService$1.run + 145(ChatService.java:145)
       at java.lang.Thread.run + 764(Thread.java:764)

The inner exception clearly states that it is a NullPointerException fired at org.apache.commons.logging.impl.LogFactoryImpl.createLogFromClass 1067(LogFactoryImpl.java:1067).

This is the catch block in LogFactoryImpl.java which causes the exception.

   } catch (ExceptionInInitializerError e) {
                // A static initializer block or the initializer code associated
                // with a static variable on the log adapter class has thrown
                // an exception.
                //
                // We treat this as meaning the adapter's underlying logging
                // library could not be found.
                String msg = e.getMessage();
                logDiagnostic("The log adapter '" + logAdapterClassName +
                              "' is unable to initialize itself when loaded via classloader " + objectId(currentCL) +
                              ": " + msg.trim());
                break;

You can clearly see that the log adapter is not found and the exception is fired because the inner exception has a null message and LogFactoryImpl tries to trim it before logging. Somehow they didn’t need to do a null check for the message. I don’t know what causes smack to fire this exception and how to handle it.

This is how we start XMPP connection.

    InetAddress addr = InetAddress.getByName(user.chat_server.serverURL);
    HostnameVerifier verifier = new HostnameVerifier() {
                @Override
                public boolean verify(String hostname, SSLSession session) {
                    return false;
                }
    };

    DomainBareJid serviceName =JidCreate.domainBareFrom(user.chat_server.serverURL);
    XMPPTCPConnectionConfiguration.Builder configBuilder = XMPPTCPConnectionConfiguration.builder();
    configBuilder.setXmppDomain(serviceName).setUsernameAndPassword(user.user_id, 
    user.chat_server.jid_password).
    setHost(user.chat_server.serverURL).
    setHostAddress(addr).
    setHostnameVerifier(verifier).
    setSendPresence(false).
    setPort(5222).
    setResource(CONNECTION_RESOURCE_ID).
    setSecurityMode(ConnectionConfiguration.SecurityMode.disabled).
                    setSendPresence(true);

    connection = new XMPPTCPConnection(configBuilder.build());
    connection.addConnectionListener(this);

    createChatManager();

    SASLAuthentication.blacklistSASLMechanism("SCRAM-SHA-1");
    SASLAuthentication.blacklistSASLMechanism("DIGEST-MD5");
    SASLAuthentication.unBlacklistSASLMechanism("PLAIN");
 
    ConnectAndLoginAsyncTask connectAndLoginAsyncTask = new ConnectAndLoginAsyncTask();
    connectAndLoginAsyncTask.execute(connection);

...

    private static class ConnectAndLoginAsyncTask extends     
    AsyncTask<AbstractXMPPConnection, Integer, Integer> {
    @Override
    protected Integer doInBackground(AbstractXMPPConnection... params) {
    AbstractXMPPConnection connection = params[0];
        try {
          if (!connection.isConnected())
            connection.connect();
        } catch (Exception e) {
          e.printStackTrace();
        }

        try {
          if (!connection.isAuthenticated())
            connection.login();
        } catch (Exception e) {
          e.printStackTrace();
        }
       return 1;
      }
    }

build.grandle

ext {
    smackVersion = '4.3.2'
    supportLibVersion = '28.0.1'
    compileSdkVersion = 28
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'androidx.appcompat:appcompat:1.1.0-rec01'
    implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0-alpha02'
    implementation 'androidx.recyclerview:recyclerview:1.1.0-beta01'
    implementation 'androidx.legacy:legacy-support-core-ui:1.0.0'
    implementation 'com.google.android.material:material:1.1.0-alpha07'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta2'
    implementation 'com.google.firebase:firebase-config:18.0.0'

    // Firebase
    implementation 'com.google.firebase:firebase-core:17.0.0'
    implementation 'com.google.firebase:firebase-messaging:19.0.1'
    implementation 'com.crashlytics.sdk.android:crashlytics:2.10.1'

    //Smack
    implementation "org.igniterealtime.smack:smack-tcp:$smackVersion"
    implementation "org.igniterealtime.smack:smack-experimental:$smackVersion"
    implementation "org.igniterealtime.smack:smack-android:$smackVersion"
    implementation "org.igniterealtime.smack:smack-im:$smackVersion"