首页 > 解决方案 > 在 Android 上禁用 log4j JMX

问题描述

我正在尝试将Hyperledger Fabric Java SDK v1.4 移植到 Android(API 级别 26)。SDK 使用 Log4j v2.13。Log4j 并没有针对 android 进行优化。我收到以下错误:

I/System.out: WARNING: sun.reflect.Reflection.getCallerClass is not supported. This will impact performance.
I/icandroidsampl: Rejecting re-init on previously-failed class java.lang.Class<org.apache.logging.log4j.core.lookup.JmxRuntimeInputArgumentsLookup>: java.lang.NoClassDefFoundError: Failed resolution of: Ljava/lang/management/ManagementFactory;
        at void org.apache.logging.log4j.core.lookup.JmxRuntimeInputArgumentsLookup.<clinit>() (JmxRuntimeInputArgumentsLookup.java:35)
        at java.lang.Object java.lang.reflect.Constructor.newInstance0(java.lang.Object[]) (Constructor.java:-2)
        at java.lang.Object java.lang.reflect.Constructor.newInstance(java.lang.Object[]) (Constructor.java:343)
        at java.lang.Object org.apache.logging.log4j.util.LoaderUtil.newInstanceOf(java.lang.Class) (LoaderUtil.java:185)
        at java.lang.Object org.apache.logging.log4j.util.LoaderUtil.newInstanceOf(java.lang.String) (LoaderUtil.java:207)
        at java.lang.Object org.apache.logging.log4j.util.LoaderUtil.newCheckedInstanceOf(java.lang.String, java.lang.Class) (LoaderUtil.java:228)
        at java.lang.Object org.apache.logging.log4j.core.util.Loader.newCheckedInstanceOf(java.lang.String, java.lang.Class) (Loader.java:311)
        at void org.apache.logging.log4j.core.lookup.Interpolator.<init>(java.util.Map) (Interpolator.java:120)
        at void org.apache.logging.log4j.core.config.AbstractConfiguration.<init>(org.apache.logging.log4j.core.LoggerContext, org.apache.logging.log4j.core.config.ConfigurationSource) (AbstractConfiguration.java:129)
        at void org.apache.logging.log4j.core.config.NullConfiguration.<init>() (NullConfiguration.java:32)
        at void org.apache.logging.log4j.core.LoggerContext.<clinit>() (LoggerContext.java:86)
        at org.apache.logging.log4j.core.LoggerContext org.apache.logging.log4j.core.selector.ClassLoaderContextSelector.createContext(java.lang.String, java.net.URI) (ClassLoaderContextSelector.java:229)
        at org.apache.logging.log4j.core.LoggerContext org.apache.logging.log4j.core.selector.ClassLoaderContextSelector.locateContext(java.lang.ClassLoader, java.net.URI) (ClassLoaderContextSelector.java:203)
        at org.apache.logging.log4j.core.LoggerContext org.apache.logging.log4j.core.selector.ClassLoaderContextSelector.getContext(java.lang.String, java.lang.ClassLoader, boolean, java.net.URI) (ClassLoaderContextSelector.java:128)
        at org.apache.logging.log4j.core.LoggerContext org.apache.logging.log4j.core.selector.ClassLoaderContextSelector.getContext(java.lang.String, java.lang.ClassLoader, boolean) (ClassLoaderContextSelector.java:115)
        at org.apache.logging.log4j.core.LoggerContext org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(java.lang.String, java.lang.ClassLoader, java.lang.Object, boolean) (Log4jContextFactory.java:148)
        at org.apache.logging.log4j.spi.LoggerContext org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(java.lang.String, java.lang.ClassLoader, java.lang.Object, boolean) (Log4jContextFactory.java:45)
        at org.apache.logging.log4j.spi.LoggerContext org.apache.logging.log4j.LogManager.getContext(java.lang.ClassLoader, boolean) (LogManager.java:194)
        at org.apache.logging.log4j.spi.LoggerContext org.apache.logging.log4j.spi.AbstractLoggerAdapter.getContext(java.lang.Class) (AbstractLoggerAdapter.java:138)
        at org.apache.logging.log4j.spi.LoggerContext org.apache.logging.log4j.jcl.LogAdapter.getContext() (LogAdapter.java:39)
        at java.lang.Object org.apache.logging.log4j.spi.AbstractLoggerAdapter.getLogger(java.lang.String) (AbstractLoggerAdapter.java:48)
        at org.apache.commons.logging.Log org.apache.logging.log4j.jcl.LogFactoryImpl.getInstance(java.lang.String) (LogFactoryImpl.java:40)
        at org.apache.commons.logging.Log org.apache.logging.log4j.jcl.LogFactoryImpl.getInstance(java.lang.Class) (LogFactoryImpl.java:55)
        at org.apache.commons.logging.Log org.apache.commons.logging.LogFactory.getLog(java.lang.Class) (LogFactory.java:655)
        at void org.hyperledger.fabric.gateway.impl.GatewayImpl.<clinit>() (GatewayImpl.java:55)
        at java.util.concurrent.TimeUnit org.hyperledger.fabric.gateway.impl.GatewayImpl.access$000() (GatewayImpl.java:54)
        at void org.hyperledger.fabric.gateway.impl.GatewayImpl$Builder.<init>() (GatewayImpl.java:71)
        at org.hyperledger.fabric.gateway.Gateway$Builder org.hyperledger.fabric.gateway.Gateway.createBuilder() (Gateway.java:87)
        at java.lang.String tubs.ibr.fabricandroidsample.MainActivity$FabricRequestTask.doInBackground(java.lang.Object[]) (MainActivity.java:78)
        at java.lang.Object tubs.ibr.fabricandroidsample.MainActivity$FabricRequestTask.doInBackground(java.lang.Object[]) (MainActivity.java:70)
        at java.lang.Object android.os.AsyncTask$2.call() (AsyncTask.java:333)
        at void java.util.concurrent.FutureTask.run() (FutureTask.java:266)
        at void android.os.AsyncTask$SerialExecutor$1.run() (AsyncTask.java:245)
        at void java.util.concurrent.ThreadPoolExecutor.runWorker(java.util.concurrent.ThreadPoolExecutor$Worker) (ThreadPoolExecutor.java:1167)
        at void java.util.concurrent.ThreadPoolExecutor$Worker.run() (ThreadPoolExecutor.java:641)
I/icandroidsampl:     at void java.lang.Thread.run() (Thread.java:764)
    Caused by: java.lang.ClassNotFoundException: Didn't find class "java.lang.management.ManagementFactory" on path: DexPathList[[zip file "/data/app/tubs.ibr.fabricandroidsample-48U2GXMv9D0UPIKFDpmpOA==/base.apk"],nativeLibraryDirectories=[/data/app/tubs.ibr.fabricandroidsample-48U2GXMv9D0UPIKFDpmpOA==/lib/x86, /system/lib]]
        at java.lang.Class dalvik.system.BaseDexClassLoader.findClass(java.lang.String) (BaseDexClassLoader.java:134)
        at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String, boolean) (ClassLoader.java:379)
        at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String) (ClassLoader.java:312)
        at void org.apache.logging.log4j.core.lookup.JmxRuntimeInputArgumentsLookup.<clinit>() (JmxRuntimeInputArgumentsLookup.java:35)
        at java.lang.Object java.lang.reflect.Constructor.newInstance0(java.lang.Object[]) (Constructor.java:-2)
        at java.lang.Object java.lang.reflect.Constructor.newInstance(java.lang.Object[]) (Constructor.java:343)
        at java.lang.Object org.apache.logging.log4j.util.LoaderUtil.newInstanceOf(java.lang.Class) (LoaderUtil.java:185)
        at java.lang.Object org.apache.logging.log4j.util.LoaderUtil.newInstanceOf(java.lang.String) (LoaderUtil.java:207)
        at java.lang.Object org.apache.logging.log4j.util.LoaderUtil.newCheckedInstanceOf(java.lang.String, java.lang.Class) (LoaderUtil.java:228)
        at java.lang.Object org.apache.logging.log4j.core.util.Loader.newCheckedInstanceOf(java.lang.String, java.lang.Class) (Loader.java:311)
        at void org.apache.logging.log4j.core.lookup.Interpolator.<init>(java.util.Map) (Interpolator.java:120)
        at void org.apache.logging.log4j.core.config.AbstractConfiguration.<init>(org.apache.logging.log4j.core.LoggerContext, org.apache.logging.log4j.core.config.ConfigurationSource) (AbstractConfiguration.java:129)
        at void org.apache.logging.log4j.core.config.NullConfiguration.<init>() (NullConfiguration.java:32)
        at void org.apache.logging.log4j.core.LoggerContext.<clinit>() (LoggerContext.java:86)
        at org.apache.logging.log4j.core.LoggerContext org.apache.logging.log4j.core.selector.ClassLoaderContextSelector.createContext(java.lang.String, java.net.URI) (ClassLoaderContextSelector.java:229)
        at org.apache.logging.log4j.core.LoggerContext org.apache.logging.log4j.core.selector.ClassLoaderContextSelector.locateContext(java.lang.ClassLoader, java.net.URI) (ClassLoaderContextSelector.java:203)
        at org.apache.logging.log4j.core.LoggerContext org.apache.logging.log4j.core.selector.ClassLoaderContextSelector.getContext(java.lang.String, java.lang.ClassLoader, boolean, java.net.URI) (ClassLoaderContextSelector.java:128)
        at org.apache.logging.log4j.core.LoggerContext org.apache.logging.log4j.core.selector.ClassLoaderContextSelector.getContext(java.lang.String, java.lang.ClassLoader, boolean) (ClassLoaderContextSelector.java:115)
        at org.apache.logging.log4j.core.LoggerContext org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(java.lang.String, java.lang.ClassLoader, java.lang.Object, boolean) (Log4jContextFactory.java:148)
        at org.apache.logging.log4j.spi.LoggerContext org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(java.lang.String, java.lang.ClassLoader, java.lang.Object, boolean) (Log4jContextFactory.java:45)
        at org.apache.logging.log4j.spi.LoggerContext org.apache.logging.log4j.LogManager.getContext(java.lang.ClassLoader, boolean) (LogManager.java:194)
        at org.apache.logging.log4j.spi.LoggerContext org.apache.logging.log4j.spi.AbstractLoggerAdapter.getContext(java.lang.Class) (AbstractLoggerAdapter.java:138)
        at org.apache.logging.log4j.spi.LoggerContext org.apache.logging.log4j.jcl.LogAdapter.getContext() (LogAdapter.java:39)
        at java.lang.Object org.apache.logging.log4j.spi.AbstractLoggerAdapter.getLogger(java.lang.String) (AbstractLoggerAdapter.java:48)
I/icandroidsampl:     at org.apache.commons.logging.Log org.apache.logging.log4j.jcl.LogFactoryImpl.getInstance(java.lang.String) (LogFactoryImpl.java:40)
        at org.apache.commons.logging.Log org.apache.logging.log4j.jcl.LogFactoryImpl.getInstance(java.lang.Class) (LogFactoryImpl.java:55)
        at org.apache.commons.logging.Log org.apache.commons.logging.LogFactory.getLog(java.lang.Class) (LogFactory.java:655)
        at void org.hyperledger.fabric.gateway.impl.GatewayImpl.<clinit>() (GatewayImpl.java:55)
        at java.util.concurrent.TimeUnit org.hyperledger.fabric.gateway.impl.GatewayImpl.access$000() (GatewayImpl.java:54)
        at void org.hyperledger.fabric.gateway.impl.GatewayImpl$Builder.<init>() (GatewayImpl.java:71)
        at org.hyperledger.fabric.gateway.Gateway$Builder org.hyperledger.fabric.gateway.Gateway.createBuilder() (Gateway.java:87)
        at java.lang.String tubs.ibr.fabricandroidsample.MainActivity$FabricRequestTask.doInBackground(java.lang.Object[]) (MainActivity.java:78)
        at java.lang.Object tubs.ibr.fabricandroidsample.MainActivity$FabricRequestTask.doInBackground(java.lang.Object[]) (MainActivity.java:70)
        at java.lang.Object android.os.AsyncTask$2.call() (AsyncTask.java:333)
        at void java.util.concurrent.FutureTask.run() (FutureTask.java:266)
        at void android.os.AsyncTask$SerialExecutor$1.run() (AsyncTask.java:245)
        at void java.util.concurrent.ThreadPoolExecutor.runWorker(java.util.concurrent.ThreadPoolExecutor$Worker) (ThreadPoolExecutor.java:1167)
        at void java.util.concurrent.ThreadPoolExecutor$Worker.run() (ThreadPoolExecutor.java:641)
        at void java.lang.Thread.run() (Thread.java:764)

发生这种情况是因为 java.lang.management.ManagementFactory 未包含在 Android 运行时中。

所以,我试图禁用 JMX。没有成功。同样的错误。像系统属性这样的接缝不在库的“范围”内?这怎么可能?

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        System.setProperty("log4j2.disable.jmx","true");

        [...]
    }
[...]
}

我也试过这个:https ://loune.net/2016/05/using-log4j2-2-3-with-android/ 。没有成功。同样的错误。

问题是,我正在使用的库中使用了 Log4j。所以我不是在寻找一种在 Android 中使用日志记录的方法,而是一种在 Android 中配置 Log4j 的方法,因此它停止抛出异常。

尽管有异常,但代码实际上运行。

标签: javaandroidlog4jhyperledger-fabric

解决方案


Log4j 2 不正式支持 Android。这主要是因为没有一个 Log4j 提交者是为 Android 开发的。也就是说,如果我们有参与者可以帮助使其正常工作并验证新版本,我们将愿意让它工作。我建议您加入 Log4j 开发人员列表并提供您可以提供的任何帮助。这主要包括报告上述错误、可能提交补丁请求和测试修复。话虽如此,由于 Android 对 JDK 中的类的限制,我不能保证所有问题都可以解决,但我们很乐意尝试。

在说了所有这些之后,在查看当前代码时,您应该只是收到 JMX 不可用的警告,并且应该继续初始化。您还没有说您尝试使用的 Log4j 版本,但您所经历的不应该是当前的行为。

最后一点。在查看上面的堆栈跟踪时,有问题的代码不依赖于 Log4j。它使用 Apache Commons Logging。大概您在项目中有 log4j-jcl jar,这就是 Log4j 参与其中的原因。您可以改为将 Commons Logging 调用路由到任何东西。


推荐阅读