[slf4j-dev] svn commit: r1148 - in slf4j/trunk/slf4j-ext/src/main/java/org/slf4j: agent instrumentation

ravn at slf4j.org ravn at slf4j.org
Tue Sep 23 23:25:23 CEST 2008


Author: ravn
Date: Tue Sep 23 23:25:23 2008
New Revision: 1148

Added:
   slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/instrumentation/AddEntryExitLoggingTransformer.java   (contents, props changed)
Modified:
   slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/agent/AgentMain.java

Log:
moved instrumentation methods from AgentMain to AddEntryExitLogginTransformer

Modified: slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/agent/AgentMain.java
==============================================================================
--- slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/agent/AgentMain.java	(original)
+++ slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/agent/AgentMain.java	Tue Sep 23 23:25:23 2008
@@ -7,19 +7,13 @@
 import java.util.HashSet;
 import java.util.Set;
 
-import javassist.CannotCompileException;
-import javassist.ClassPool;
-import javassist.CtBehavior;
-import javassist.CtClass;
-import javassist.CtField;
-import javassist.NotFoundException;
+import org.slf4j.instrumentation.AddEntryExitLoggingTransformer;
 
-import org.slf4j.instrumentation.JavassistHelper;
-
-public class AgentMain implements ClassFileTransformer {
+public class AgentMain {
 
 	public static void premain(String agentArgument,
 			Instrumentation instrumentation) {
+
 		if (agentArgument != null) {
 			String[] args = agentArgument.split(",");
 			Set<String> argSet = new HashSet<String>(Arrays.asList(args));
@@ -37,91 +31,8 @@
 			}
 			// ... more agent option handling here
 		}
-		instrumentation.addTransformer(new AgentMain());
-	}
-
-	// Determine name of logger
-
-	String def = "private static org.slf4j.Logger " + "_log" + ";";
-	String ifLog = "if (_log.isDebugEnabled())";
-
-	String[] ignore = new String[] { "sun/", "java/", "javax/", "org/slf4j/",
-			"ch/qos/logback/" };
-
-	//
-	// The transform(...) method calls doClass(...) if the class name does not
-	// start with any of the prefixes it has been told to ignore (note that the
-	// separators are slashes, not dots).
-
-	public byte[] transform(ClassLoader loader, String className, Class<?> clazz,
-			java.security.ProtectionDomain domain, byte[] bytes) {
-
-		for (int i = 0; i < ignore.length; i++) {
-			if (className.startsWith(ignore[i])) {
-				return bytes;
-			}
-		}
-		//System.out.println("Adding to " + className);
-		return doClass(className, clazz, bytes);
-	}
 
-	//
-	// The doClass(...) method uses javassist to analyze the byte stream. If it
-	// is a real class, a logger field is added and initialized to the name of
-	// the class. Each non-empty method is then processed with doMethod(...).
-	// The finally-clause ensures that the class definition is removed again
-	// from the javassist pools to keep memory usage down.
-	//
-	// Note: The logger variable has been named _log. In a production version an
-	// unused variable name should be found and used.
-
-	private byte[] doClass(String name, Class<?> clazz, byte[] b) {
-		ClassPool pool = ClassPool.getDefault();
-		CtClass cl = null;
-		try {
-			cl = pool.makeClass(new java.io.ByteArrayInputStream(b));
-			if (cl.isInterface() == false) {
-
-				CtField field = CtField.make(def, cl);
-				String getLogger = "org.slf4j.LoggerFactory.getLogger("
-						+ name.replace('/', '.') + ".class);";
-				cl.addField(field, getLogger);
-				System.out.println(getLogger);
-
-				CtBehavior[] methods = cl.getDeclaredBehaviors();
-				for (int i = 0; i < methods.length; i++) {
-					if (methods[i].isEmpty() == false) {
-						doMethod(methods[i]);
-					}
-				}
-				b = cl.toBytecode();
-			}
-		} catch (Exception e) {
-			System.err.println("Could not instrument  " + name
-					+ ",  exception : " + e.getMessage());
-		} finally {
-			if (cl != null) {
-				cl.detach();
-			}
-		}
-		return b;
+		instrumentation.addTransformer(new AddEntryExitLoggingTransformer());
 	}
 
-	// The doMethod(...) class creates "_log.info(...)" snippets to insert at
-	// the beginning and end of each method. Both contain the parameters (as
-	// they may have changed), and the end method statement contain the return
-	// value for non-void methods (which is available as $_ in the javassist
-	// compiler).
-
-	private void doMethod(CtBehavior method) throws NotFoundException,
-			CannotCompileException {
-
-		String signature = JavassistHelper.getSignature(method);
-		String returnValue = JavassistHelper.returnValue(method);
-
-		method.insertBefore(ifLog + "_log" + ".info(\">> " + signature + ");");
-
-		method.insertAfter(ifLog + "_log" + ".info(\"<< " + signature
-				+ returnValue + ");");
-	}
 }
\ No newline at end of file

Added: slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/instrumentation/AddEntryExitLoggingTransformer.java
==============================================================================
--- (empty file)
+++ slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/instrumentation/AddEntryExitLoggingTransformer.java	Tue Sep 23 23:25:23 2008
@@ -0,0 +1,85 @@
+/**
+ * 
+ */
+package org.slf4j.instrumentation;
+
+import java.io.ByteArrayInputStream;
+import java.lang.instrument.ClassFileTransformer;
+
+import javassist.CannotCompileException;
+import javassist.ClassPool;
+import javassist.CtBehavior;
+import javassist.CtClass;
+import javassist.CtField;
+import javassist.NotFoundException;
+
+
+public class AddEntryExitLoggingTransformer implements
+		ClassFileTransformer {
+	
+	final String def = "private static org.slf4j.Logger " + "_log" + ";";
+	final String ifLog = "if (_log.isDebugEnabled())";
+	String[] ignore = new String[] { "sun/", "java/", "javax/", "org/slf4j/",
+			"ch/qos/logback/" };
+
+	public byte[] transform(ClassLoader loader, String className, Class<?> clazz,
+			java.security.ProtectionDomain domain, byte[] bytes) {
+
+		for (int i = 0; i < ignore.length; i++) {
+			if (className.startsWith(ignore[i])) {
+				return bytes;
+			}
+		}
+		//System.out.println("Adding to " + className);
+		return doClass(className, clazz, bytes);
+	}
+
+	//
+	// The transform(...) method calls doClass(...) if the class name does not
+	// start with any of the prefixes it has been told to ignore (note that the
+	// separators are slashes, not dots).
+
+	private byte[] doClass(String name, Class<?> clazz, byte[] b) {
+		ClassPool pool = ClassPool.getDefault();
+		CtClass cl = null;
+		try {
+			cl = pool.makeClass(new ByteArrayInputStream(b));
+			if (cl.isInterface() == false) {
+
+				CtField field = CtField.make(def, cl);
+				String getLogger = "org.slf4j.LoggerFactory.getLogger("
+						+ name.replace('/', '.') + ".class);";
+				cl.addField(field, getLogger);
+				System.out.println(getLogger);
+
+				CtBehavior[] methods = cl.getDeclaredBehaviors();
+				for (int i = 0; i < methods.length; i++) {
+					if (methods[i].isEmpty() == false) {
+						doMethod(methods[i]);
+					}
+				}
+				b = cl.toBytecode();
+			}
+		} catch (Exception e) {
+			System.err.println("Could not instrument  " + name
+					+ ",  exception : " + e.getMessage());
+		} finally {
+			if (cl != null) {
+				cl.detach();
+			}
+		}
+		return b;
+	}
+
+	private void doMethod(CtBehavior method) throws NotFoundException,
+			CannotCompileException {
+
+		String signature = JavassistHelper.getSignature(method);
+		String returnValue = JavassistHelper.returnValue(method);
+
+		method.insertBefore(ifLog + "_log" + ".info(\">> " + signature + ");");
+
+		method.insertAfter(ifLog + "_log" + ".info(\"<< " + signature
+				+ returnValue + ");");
+	}
+}
\ No newline at end of file



More information about the slf4j-dev mailing list