java - log4j2 日志记录仅在一个类中起作用

标签 java log4j2

我想在类 JarClassLoaderMenu 中启用日志记录。

Menu 类中它可以工作(日志打印到文件和控制台)。但是日志记录在 JarClassLoader 中不起作用(日志记录在控制台或文件中都不起作用)。

为了简单起见,我仅将消息添加到 JarClassLoader 的类构造函数中,并在 main(String[] args) 方法的开头添加一条消息。

log4j2.properties

name=PropertiesConfig
property.filename=classloading/menu-module/logs
appenders=console, file

appender.console.type=Console
appender.console.name=STDOUT
appender.console.layout.type=PatternLayout
appender.console.layout.pattern=[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n

appender.file.type=File
appender.file.name=LOGFILE
appender.file.fileName=${filename}/propertieslogs.log
appender.file.layout.type=PatternLayout
appender.file.layout.pattern=[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n

rootLogger.level=info
rootLogger.appenderRefs=stdout
rootLogger.appenderRef.stdout.ref=STDOUT

loggers=file
logger.file.name=com.example.classloading
logger.file.level=info
logger.file.appenderRefs=file
logger.file.appenderRef.file.ref=LOGFILE

JarClassLoader

package com.example.classloading;

import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class JarClassLoader extends ClassLoader {

    private static final Logger log = LogManager.getLogger(JarClassLoader.class);

    private HashMap<String, Class<?>> cache = new HashMap<String, Class<?>>();
    private String jarFileName;
    private String packageName;
    private static String WARNING = "Warning : No jar file found. Packet unmarshalling won't be possible. Please verify your classpath";

    public JarClassLoader(String jarFileName, String packageName) {         
        log.info(">> inside JarClassLoader");

        this.jarFileName = jarFileName;
        this.packageName = packageName;

        cacheClasses();
    }

    private void cacheClasses() {
        try {
            JarFile jarFile = new JarFile(jarFileName);
            Enumeration entries = jarFile.entries();
            while (entries.hasMoreElements()) {
                JarEntry jarEntry = (JarEntry) entries.nextElement();
                // simple class validation based on package name
                if (match(normalize(jarEntry.getName()), packageName)) {
                    byte[] classData = loadClassData(jarFile, jarEntry);
                    if (classData != null) {
                        Class<?> clazz = defineClass(stripClassName(normalize(jarEntry.getName())), classData, 0, classData.length);
                        cache.put(clazz.getName(), clazz);
                        System.out.println("== class " + clazz.getName() + " loaded in cache");
                    }
                }
            }
        }
        catch (IOException IOE) {
            System.out.println(WARNING);
        }
    }

    public synchronized Class<?> loadClass(String name) throws ClassNotFoundException {
        Class<?> result = cache.get(name);
        if (result == null)
            result = cache.get(packageName + "." + name);
        if (result == null)
            result = super.findSystemClass(name);    
        System.out.println("== loadClass(" + name + ")");    
        return result;
    }

    private String stripClassName(String className) {
        return className.substring(0, className.length() - 6);
    }

    private String normalize(String className) {
        return className.replace('/', '.');
    }

    private boolean match(String className, String packageName) {
        return className.startsWith(packageName) && className.endsWith(".class");
    }

    private byte[] loadClassData(JarFile jarFile, JarEntry jarEntry) throws IOException {
        long size = jarEntry.getSize();
        if (size == -1 || size == 0)
            return null;

        byte[] data = new byte[(int)size];
        InputStream in = jarFile.getInputStream(jarEntry);
        in.read(data);

        return data;
    }
}

菜单

package com.example.classloading;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.Scanner;

public class Menu {

    private static final Logger log = LogManager.getLogger();

    public static void main(String[] args) {

        int select;
        do {
            log.info(">> menu started");

            System.out.println("=== MENU ===");
            System.out.println("This is a simple multi-module project that can dynamically load modules.");
            System.out.println("1. Load and run simple-module");
            System.out.println("2. Load and run module in jar from ...");
            System.out.println("0. EXIT");

            Scanner scanner = new Scanner(System.in);
            select = scanner.nextInt();

            switch (select) {
                case 1: {
                    JarClassLoader jarClassLoader = new JarClassLoader("classloading/simple-module/target/simple-module-1.0-SNAPSHOT.jar", "com.example.classloading");
                    try {
                        Class<?> clas = jarClassLoader.loadClass("com.example.classloading.SimpleModule");
                        Module sample = (Module) clas.newInstance();
                        sample.run();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;
                }
                case 2: {
                    System.out.print("    Path to jar: ");
                    String jarFileName = scanner.next();
                    System.out.print("    Package name: ");
                    String packageName = scanner.next();
                    System.out.print("    Class to load and run: ");
                    String classToLoad = scanner.next();

                    JarClassLoader jarClassLoader = new JarClassLoader(jarFileName, packageName);
                    try {
                        Class<?> clas = jarClassLoader.loadClass(classToLoad);
                        Module sample = (Module) clas.newInstance();
                        sample.run();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;
                }
            }
        } while (select != 0);
    }

}
<小时/>

output

<小时/>

那么,为什么日志记录在 JarClassLoader 类中不起作用?

最佳答案

我已经运行了你的代码,日志记录没有问题。当我运行确切的代码时,输​​出如下;

[INFO ] 2017-04-09 20:07:15.208 [main] Menu - >> menu started
=== MENU ===
This is a simple multi-module project that can dynamically load modules.
1. Load and run simple-module
2. Load and run module in jar from ...
0. EXIT
1
[INFO ] 2017-04-09 20:07:20.681 [main] JarClassLoader - >> inside JarClassLoader

在您的屏幕截图中,我没有看到您在控制台中输入了“1”或“2”作为选择。只要您不从控制台输入任何内容,java 程序就会等待输入,因此,它永远不会到达完成日志记录的行。

关于java - log4j2 日志记录仅在一个类中起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43300114/

相关文章:

java - 一步一步的 gflot 教程?

java - log4j2和syslog,使用RFC5424格式不显示日志消息的varargs部分

java - 配置 log4j 在登录模式之前调用静态函数

java - 如何使用 log4j2 编写自定义 Web 服务附加程序?

java - 如何使用 Android Studio 在 Android 应用程序中可视化音频文件?

java - 单例中的单例

java - log4j2 到链锯不工作 - 链锯的 'Zeroconf' 选项卡中没有显示任何内容

java - Log4J2 配置中的主要参数

java - RCP:如何同步 MMenuItem 和 MToolItem 的状态

java - Javafx8 Webview 支持哪些 CSS3 特性?