diff --git a/src/main/java/com/profiler/AgentClassLoader.java b/src/main/java/com/profiler/AgentClassLoader.java index c7243f0ce..b13eb7416 100644 --- a/src/main/java/com/profiler/AgentClassLoader.java +++ b/src/main/java/com/profiler/AgentClassLoader.java @@ -1,9 +1,13 @@ package com.profiler; +import com.profiler.logging.LoggerBinder; + +import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; +import java.util.Enumeration; /** * @@ -13,6 +17,7 @@ public class AgentClassLoader { private URLClassLoader classLoader; private String bootClass = "com.profiler.AgentBootStrap"; private String bootMethod = "boot"; + private Object agentBootStrap; public AgentClassLoader(URL[] urls) { ClassLoader classLoader = AgentClassLoader.class.getClassLoader(); @@ -26,34 +31,69 @@ public class AgentClassLoader { public void setBootMethod(String bootMethod) { this.bootMethod = bootMethod; } + public void test() { + URL resource = this.classLoader.getResource("/log4j.xml"); + System.out.println("log4j.xml=" + resource); + URL resource1 = this.classLoader.getResource("/nhn_source/hippo_project/deploy/agent/agentlib/lib/log4j.xml"); + System.out.println("log4j.xml=" + resource1); + + URL[] aaa = this.classLoader.getURLs(); + for (URL url : aaa) { + System.out.println("" + url); + } + + URL resource2 = classLoader.getResource("."); + System.out.println("resource2:" + resource2); + try { + Enumeration resources = this.classLoader.getResources("."); + while (resources.hasMoreElements()) { + URL url = resources.nextElement(); + System.out.println("" + url); + } + } catch (IOException e) { + e.printStackTrace(); + } + } public void boot() { try{ Class bootStrap = this.classLoader.loadClass(bootClass); - Object agentBootStrap = bootStrap.newInstance(); - - Method bootMethod = bootStrap.getDeclaredMethod(this.bootMethod); - - Thread currentThread = Thread.currentThread(); - ClassLoader before = currentThread.getContextClassLoader(); - currentThread.setContextClassLoader(this.classLoader); - try { - bootMethod.invoke(agentBootStrap); - } finally { - currentThread.setContextClassLoader(before); - } + agentBootStrap = bootStrap.newInstance(); + invoke(bootStrap, this.bootMethod); } catch (ClassNotFoundException e) { throw new RuntimeException("boot class not found. Caused:" + e.getMessage(), e); - } catch (NoSuchMethodException e) { - throw new RuntimeException("boot method not found. Caused:" + e.getMessage(), e); - } catch (InvocationTargetException e) { - throw new RuntimeException(this.bootMethod + "() fail. Caused:" + e.getMessage(), e); } catch (InstantiationException e) { throw new RuntimeException("boot create fail. Caused:" + e.getMessage(), e); } catch (IllegalAccessException e) { throw new RuntimeException("boot method invoke fail. Caused:" + e.getMessage(), e); } + } + private Object invoke(Class clazz, String method) { + Method bootMethod = null; + try { + bootMethod = clazz.getDeclaredMethod(method); + } catch (NoSuchMethodException e) { + throw new RuntimeException("boot method not found. Caused:" + e.getMessage(), e); + } + + final Thread currentThread = Thread.currentThread(); + ClassLoader before = currentThread.getContextClassLoader(); + currentThread.setContextClassLoader(this.classLoader); + try { + return bootMethod.invoke(agentBootStrap); + } catch (InvocationTargetException e) { + throw new RuntimeException(this.bootMethod + "() fail. Caused:" + e.getMessage(), e); + } catch (IllegalAccessException e) { + throw new RuntimeException("boot method invoke fail. Caused:" + e.getMessage(), e); + } + finally { + currentThread.setContextClassLoader(before); + } + } + + public LoggerBinder initializeLoggerBinder() { + return (LoggerBinder) invoke(agentBootStrap.getClass(), "initializeLoggerBinder"); } } diff --git a/src/main/java/com/profiler/ClassPathResolver.java b/src/main/java/com/profiler/ClassPathResolver.java index 8677bd80c..b4537b499 100644 --- a/src/main/java/com/profiler/ClassPathResolver.java +++ b/src/main/java/com/profiler/ClassPathResolver.java @@ -29,15 +29,25 @@ public class ClassPathResolver { private String agentJarFullPath; private String agentDirPath; private Pattern agentPattern; + private List fileExtensionList; public ClassPathResolver() { - this.classPath = getClassPathFromSystemProperty(); - this.agentPattern = DEFAULT_AGENT_PATTERN; + this(getClassPathFromSystemProperty()); } + public ClassPathResolver(String classPath) { this.classPath = classPath; this.agentPattern = DEFAULT_AGENT_PATTERN; + this.fileExtensionList = getDefaultFileExtensionList(); + } + + public List getDefaultFileExtensionList() { + List extensionList = new ArrayList(); + extensionList.add("jar"); + extensionList.add("xml"); + extensionList.add("properties"); + return extensionList; } public ClassPathResolver(String classPath, String agentPattern) { @@ -53,7 +63,7 @@ public class ClassPathResolver { this.classPath = getClassPathFromSystemProperty(); } - public String getClassPathFromSystemProperty() { + public static String getClassPathFromSystemProperty() { return System.getProperty("java.class.path"); } @@ -119,6 +129,9 @@ public class ClassPathResolver { jarURLList.add(url); } } + // agentDir 패스도 넣어야 xml을 찾을 때 해당 패스에서 찾음. + URL agentDirUri = toURI(new File(agentLibPath)); + jarURLList.add(agentDirUri); return jarURLList; } @@ -136,7 +149,13 @@ public class ClassPathResolver { return libDir.listFiles(new FileFilter() { @Override public boolean accept(File pathname) { - return pathname.getName().lastIndexOf(".jar") != -1; + String path = pathname.getName(); + for (String extension : fileExtensionList) { + if (path.lastIndexOf("." + extension) != -1) { + return true; + } + } + return false; } }); } diff --git a/src/main/java/com/profiler/TomcatProfiler.java b/src/main/java/com/profiler/TomcatProfiler.java index dd55fd238..cccaec3b2 100644 --- a/src/main/java/com/profiler/TomcatProfiler.java +++ b/src/main/java/com/profiler/TomcatProfiler.java @@ -14,6 +14,8 @@ import java.util.logging.Logger; import com.profiler.common.ServiceType; import com.profiler.config.ProfilerConfig; +import com.profiler.logging.LoggerBinder; +import com.profiler.logging.LoggerFactory; import com.profiler.interceptor.bci.ByteCodeInstrumentor; import com.profiler.interceptor.bci.JavaAssistByteCodeInstrumentor; import com.profiler.modifier.DefaultModifierRegistry; @@ -53,11 +55,16 @@ public class TomcatProfiler implements ClassFileTransformer { List libUrlList = resolveLib(classPathResolver); AgentClassLoader agentClassLoader = new AgentClassLoader(libUrlList.toArray(new URL[libUrlList.size()])); agentClassLoader.setBootClass("com.profiler.boot.BootClassTest"); +// agentClassLoader.test(); try { agentClassLoader.boot(); + LoggerBinder loggerBinder = agentClassLoader.initializeLoggerBinder(); + loggerBinder.getLogger("LoggerFactory initialize start"); + LoggerFactory.initialize(loggerBinder); + com.profiler.logging.Logger tomcatLogger = LoggerFactory.getLogger(TomcatProfiler.class); + tomcatLogger.info("LoggerFactory initialize end"); } catch (Exception e) { - logger.info("test error"); - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + logger.log(Level.INFO, "boot class not found", e); } try { @@ -86,7 +93,7 @@ public class TomcatProfiler implements ClassFileTransformer { return profilerConfig; } - private static List resolveLib(ClassPathResolver classPathResolver) { + private static List resolveLib(ClassPathResolver classPathResolver) { String agentJarFullPath = classPathResolver.getAgentJarFullPath(); logger.info("agentJarPath:" + agentJarFullPath); diff --git a/src/main/java/com/profiler/logging/Logger.java b/src/main/java/com/profiler/logging/Logger.java new file mode 100644 index 000000000..444482695 --- /dev/null +++ b/src/main/java/com/profiler/logging/Logger.java @@ -0,0 +1,13 @@ +package com.profiler.logging; + +/** + * + */ +public interface Logger { + + public void info(String msg); + + + public void info(String format, Object arg); + +} diff --git a/src/main/java/com/profiler/logging/LoggerBinder.java b/src/main/java/com/profiler/logging/LoggerBinder.java new file mode 100644 index 000000000..76e35b52c --- /dev/null +++ b/src/main/java/com/profiler/logging/LoggerBinder.java @@ -0,0 +1,10 @@ +package com.profiler.logging; + +import com.profiler.logging.Logger; + +/** + * + */ +public interface LoggerBinder { + Logger getLogger(String name); +} diff --git a/src/main/java/com/profiler/logging/LoggerFactory.java b/src/main/java/com/profiler/logging/LoggerFactory.java new file mode 100644 index 000000000..9f5c131d7 --- /dev/null +++ b/src/main/java/com/profiler/logging/LoggerFactory.java @@ -0,0 +1,24 @@ +package com.profiler.logging; + +/** + * + */ +public final class LoggerFactory { + + private static LoggerBinder loggerBinder; + + public static void initialize(LoggerBinder loggerBinder) { + if (LoggerFactory.loggerBinder == null) { + System.out.println("set logger binder-------------"); + LoggerFactory.loggerBinder = loggerBinder; + } + } + + public static Logger getLogger(String name) { + return loggerBinder.getLogger(name); + } + + public static Logger getLogger(Class name) { + return getLogger(name.getName()); + } +} diff --git a/src/main/java/com/profiler/sender/UdpDataSender.java b/src/main/java/com/profiler/sender/UdpDataSender.java index ef218e5dd..7f97d2854 100644 --- a/src/main/java/com/profiler/sender/UdpDataSender.java +++ b/src/main/java/com/profiler/sender/UdpDataSender.java @@ -7,7 +7,6 @@ import java.net.InetSocketAddress; import java.net.SocketException; import java.util.ArrayList; import java.util.List; -import java.util.concurrent.CountDownLatch; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; @@ -45,7 +44,6 @@ public class UdpDataSender implements DataSender, Runnable { private HeaderTBaseSerializer serializer = new HeaderTBaseSerializer(); private AtomicBoolean allowInput = new AtomicBoolean(); - private CountDownLatch shutdownLatch = new CountDownLatch(1); public UdpDataSender(String host, int port) { Assert.notNull(host, "host must not be null"); @@ -115,8 +113,9 @@ public class UdpDataSender implements DataSender, Runnable { } try { - shutdownLatch.await(5, TimeUnit.SECONDS); + ioThread.join(5000); } catch (InterruptedException e) { + Thread.currentThread().interrupt(); logger.info("UdpDataSender stopped incompletely."); } @@ -132,7 +131,6 @@ public class UdpDataSender implements DataSender, Runnable { drain: while (true) { try { if (!allowInput.get() && isEmpty()) { - shutdownLatch.countDown(); break; } @@ -144,7 +142,6 @@ public class UdpDataSender implements DataSender, Runnable { while (true) { if (!allowInput.get() && isEmpty()) { - shutdownLatch.countDown(); break; } @@ -155,7 +152,7 @@ public class UdpDataSender implements DataSender, Runnable { } } } catch (Throwable th) { - logger.log(Level.WARNING, "Unexpected Error Cause:" + th.getMessage(), th); + logger.log(Level.WARNING, "Unexpected Error. Cause:" + th.getMessage(), th); } } } @@ -165,7 +162,7 @@ public class UdpDataSender implements DataSender, Runnable { try { sendPacket(dto); } catch (Throwable th) { - logger.log(Level.WARNING, "Unexpected Error Cause:" + th.getMessage(), th); + logger.log(Level.WARNING, "Unexpected Error. Cause:" + th.getMessage(), th); } } } diff --git a/src/test/java/com/profiler/AgentClassLoaderTest.java b/src/test/java/com/profiler/AgentClassLoaderTest.java index 1db3dff22..973d7dc7f 100644 --- a/src/test/java/com/profiler/AgentClassLoaderTest.java +++ b/src/test/java/com/profiler/AgentClassLoaderTest.java @@ -1,16 +1,19 @@ package com.profiler; -import org.junit.Assert; +import com.profiler.logging.LoggerBinder; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; -import java.net.MalformedURLException; +import java.io.IOException; import java.net.URL; import java.security.CodeSource; import java.security.ProtectionDomain; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; /** * @@ -20,22 +23,47 @@ public class AgentClassLoaderTest { private Logger logger = LoggerFactory.getLogger(this.getClass()); @Test - public void boot() throws MalformedURLException, ClassNotFoundException { + public void boot() throws IOException, ClassNotFoundException { String projectDir = getProjectLibDir(); logger.info("lib:" + projectDir); + URL[] lib = getLib(projectDir); + logger.info("lib list:" + Arrays.toString(lib)); +// String testJar = "hippoClassLoaderTest-1.0.jar"; +// logger.info("load lib:" + testJar); +// +// String testJarPath = projectDir + File.separator + testJar; +// logger.info("load testlib:" + testJarPath); +// File file = new File(testJarPath); +// Assert.assertTrue(file.exists()); +// String log4j = projectDir + File.separator + "log4j.xml"; +// File log4jFile = new File(log4j); - String testJar = "hippoClassLoaderTest-1.0.jar"; - logger.info("load lib:" + testJar); - - String testJarPath = projectDir + File.separator + testJar; - logger.info("load testlib:" + testJarPath); - File file = new File(testJarPath); - Assert.assertTrue(file.exists()); - AgentClassLoader agentClassLoader = new AgentClassLoader(new URL[]{file.toURI().toURL()}); + AgentClassLoader agentClassLoader = new AgentClassLoader(lib); agentClassLoader.setBootClass("com.profiler.boot.BootClassTest"); agentClassLoader.boot(); + + LoggerBinder loggerBinder = agentClassLoader.initializeLoggerBinder(); + com.profiler.logging.Logger test = loggerBinder.getLogger("test"); + test.info("slf4j logger test"); + + } + + private URL[] getLib(String libDir) throws IOException { + System.out.println(libDir); + File libFile = new File(libDir); + System.out.println("file ab:" + libFile.getAbsolutePath()); + System.out.println("file ca:" + libFile.getCanonicalPath()); + File[] list = libFile.listFiles(); + List arrayList = new ArrayList(); + for (File file : list) { + URL url = file.toURI().toURL(); + System.out.println(url); + arrayList.add(url); + } + + return arrayList.toArray(new URL[arrayList.size()]); } private String getProjectLibDir() { @@ -50,7 +78,7 @@ public class AgentClassLoaderTest { if (dirPath == -1) { throw new RuntimeException("target/classes/ not found"); } - String projectDir = path.substring(0, dirPath); + String projectDir = path.substring(1, dirPath); return projectDir + "src/test/lib"; } } diff --git a/src/test/lib/hippoClassLoaderTest-1.0.jar b/src/test/lib/hippoClassLoaderTest-1.0.jar index 529e5109a..93e445a3f 100644 Binary files a/src/test/lib/hippoClassLoaderTest-1.0.jar and b/src/test/lib/hippoClassLoaderTest-1.0.jar differ