我想在类JarClassLoader
和Menu
中启用日志记录。
在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;
}
}
Menu
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);
}
}
那么,为什么不在JarClassLoader
课程中记录工作?
答案 0 :(得分:1)
我已运行您的代码,日志记录没有问题。当我运行确切的代码时,输出如下;
[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
在您的屏幕截图中,我没有看到您已输入&#34; 1&#34;或&#34; 2&#34;在您的控制台中作为选择。只要您不从控制台输入任何内容,java程序就会等待输入,因此,它永远不会到达记录完成的行。