changeset 0:75652a041afb

Initial import
author Omair Majid <omajid@redhat.com>
date Fri, 22 Aug 2014 18:35:41 -0400
parents
children 6f180b7c6236
files README agent/ProfileUsingJavassist.java agent/manifest.mf attacher/Attacher.java attacher/manifest.mf lib/javassist.jar make.sh test/ContinuousObjectAllocator.java test/PrintDateAndTime.java
diffstat 9 files changed, 235 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README	Fri Aug 22 18:35:41 2014 -0400
@@ -0,0 +1,3 @@
+A simple test of java agents
+
+Run using `./make.sh`
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/ProfileUsingJavassist.java	Fri Aug 22 18:35:41 2014 -0400
@@ -0,0 +1,102 @@
+import java.io.IOException;
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.IllegalClassFormatException;
+import java.lang.instrument.Instrumentation;
+import java.lang.instrument.UnmodifiableClassException;
+import java.security.ProtectionDomain;
+import java.util.ArrayList;
+import java.util.List;
+
+import javassist.ByteArrayClassPath;
+import javassist.CannotCompileException;
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.CtMethod;
+import javassist.Modifier;
+import javassist.NotFoundException;
+
+public class ProfileUsingJavassist {
+
+    public static void premain(String agentArgs, Instrumentation instrumentation) {
+        System.out.println("premain() called");
+        ClassInstrumenter profiler = new ClassInstrumenter();
+        instrumentation.addTransformer(profiler);
+    }
+
+    public static void agentmain(String agentArgs, Instrumentation instrumentation) {
+        System.out.println("agentmain() called");
+
+        ClassInstrumenter profiler = new ClassInstrumenter();
+        instrumentation.addTransformer(profiler);
+
+        for (Class<?> klass : instrumentation.getAllLoadedClasses()) {
+            if (!instrumentation.isModifiableClass(klass)) {
+                continue;
+            }
+
+            Class<?>[] classes = new Class<?>[] { klass };
+            try {
+                instrumentation.retransformClasses(classes);
+            } catch (UnmodifiableClassException e) {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+            }
+        }
+
+    }
+
+    static class ClassInstrumenter implements ClassFileTransformer {
+
+        private static final String PREFIX = "thermostatMonitoringAgentGeneratedSynthetic";
+
+        private static List<String> ignorePackageRegexps = new ArrayList<>();
+
+        static {
+            ignorePackageRegexps.add("java\\..*");
+            ignorePackageRegexps.add("javax\\..*");
+            ignorePackageRegexps.add("com\\.sun\\..*");
+            ignorePackageRegexps.add("sun\\..*");
+            ignorePackageRegexps.add("jdk\\..*");
+        }
+
+        @Override
+        public byte[] transform(ClassLoader loader, String className,
+                Class<?> classBeingRedefined,
+                ProtectionDomain protectionDomain, byte[] classfileBuffer)
+                throws IllegalClassFormatException {
+
+            className = className.replace('/', '.');
+            for (String regex : ignorePackageRegexps) {
+                if (className.matches(regex)) {
+                    return null;
+                }
+            }
+
+            System.out.println("transforming '" + className + "'");
+            ClassPool classPool = ClassPool.getDefault();
+
+            ByteArrayClassPath byteArrayClass = new ByteArrayClassPath(className, classfileBuffer);
+            classPool.insertClassPath(byteArrayClass);
+            try {
+                CtClass klass = classPool.get(className);
+                for (CtMethod method : klass.getDeclaredMethods()) {
+                    String methodName = method.getName();
+                    int modifiers = method.getModifiers();
+                    if (!Modifier.isAbstract(modifiers) &&
+                            !Modifier.isNative(modifiers)) {
+//                        method.addLocalVariable(PREFIX + "StartTime", CtClass.longType);
+//                        method.insertBefore(PREFIX + "StartTime = System.nanoTime();");
+//                        method.insertAfter("System.out.println(\"" + methodName + " took \" + (System.nanoTime() - " + PREFIX + "StartTime));");
+                    }
+                }
+                return klass.toBytecode();
+            } catch (NotFoundException | CannotCompileException | IOException e) {
+                System.err.println("Unable to patch " + className);
+                e.printStackTrace();
+                return null;
+            }
+
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/manifest.mf	Fri Aug 22 18:35:41 2014 -0400
@@ -0,0 +1,4 @@
+Premain-Class: ProfileUsingJavassist
+Agent-Class: ProfileUsingJavassist
+Boot-Class-Path: ../lib/javassist.jar
+Can-Retransform-Classes: true
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/attacher/Attacher.java	Fri Aug 22 18:35:41 2014 -0400
@@ -0,0 +1,21 @@
+import java.io.IOException;
+
+import com.sun.tools.attach.AgentInitializationException;
+import com.sun.tools.attach.AgentLoadException;
+import com.sun.tools.attach.AttachNotSupportedException;
+import com.sun.tools.attach.VirtualMachine;
+
+public class Attacher {
+    public static void main(String[] args) {
+        String pid = args[0];
+        String agentJar = args[1];
+        try {
+            VirtualMachine vm = VirtualMachine.attach(pid);
+            vm.loadAgent(agentJar);
+        } catch (AttachNotSupportedException | IOException | AgentLoadException | AgentInitializationException e) {
+            System.err.println("Unable to attach to pid " + pid);
+            e.printStackTrace(System.err);
+            System.exit(1);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/attacher/manifest.mf	Fri Aug 22 18:35:41 2014 -0400
@@ -0,0 +1,1 @@
+Main-Class: Attacher
Binary file lib/javassist.jar has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make.sh	Fri Aug 22 18:35:41 2014 -0400
@@ -0,0 +1,52 @@
+#!/bin/bash -e
+
+set -o monitor # job control
+
+JAVA=java
+JAVAC=javac
+JAR=jar
+JAVA_HOME=$(dirname $(readlink -f $(which ${JAVAC})))/../
+TOOLS_JAR=${JAVA_HOME}/lib/tools.jar
+
+BUILD=build
+
+AGENT_SRC=agent
+AGENT_BUILD=build/agent
+AGENT_JAR_NAME=agent.jar
+
+ATTACHER_SRC=attacher
+ATTACHER_BUILD=build/attacher
+ATTACHER_JAR_NAME=attacher.jar
+
+TEST_SRC=test
+TEST_BUILD=build/test
+
+JAVASSIST_JAR=lib/javassist.jar
+
+# Remove everything
+rm -rf ${BUILD}
+
+# Build agent
+mkdir -p ${AGENT_BUILD}
+find ${AGENT_SRC} -iname '*.java' > ${BUILD}/agent-java-files
+${JAVAC} @${BUILD}/agent-java-files -cp ${JAVASSIST_JAR} -d ${AGENT_BUILD}
+${JAR} cmf ${AGENT_SRC}/manifest.mf ${BUILD}/${AGENT_JAR_NAME} -C ${AGENT_BUILD} .
+
+# Build attacher
+mkdir -p ${ATTACHER_BUILD}
+find ${ATTACHER_SRC} -iname '*.java' > ${BUILD}/attacher-java-files
+${JAVAC} @${BUILD}/attacher-java-files -cp ${TOOLS_JAR} -d ${ATTACHER_BUILD}
+${JAR} cmf ${ATTACHER_SRC}/manifest.mf ${BUILD}/${ATTACHER_JAR_NAME} -C ${ATTACHER_BUILD} .
+
+# build test programs
+mkdir -p ${TEST_BUILD}
+find ${TEST_SRC} -iname '*.java' > ${BUILD}/test-java-files
+${JAVAC} @${BUILD}/test-java-files -d ${TEST_BUILD}
+
+# Run load-agent-on-startup
+${JAVA} -javaagent:${BUILD}/${AGENT_JAR_NAME} -cp ${TEST_BUILD} PrintDateAndTime
+
+# Run load-agent-after-startup
+${JAVA} -cp ${TEST_BUILD} ContinuousObjectAllocator & PID="$!"
+${JAVA} -cp ${TOOLS_JAR}:${BUILD}/${ATTACHER_JAR_NAME} Attacher ${PID} ${BUILD}/${AGENT_JAR_NAME}
+wait %1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/ContinuousObjectAllocator.java	Fri Aug 22 18:35:41 2014 -0400
@@ -0,0 +1,24 @@
+public class ContinuousObjectAllocator {
+
+    public static void allocate() {
+        System.out.print(".");
+        int[] numbers;
+        numbers = new int[100];
+        numbers[0] = 0;
+        numbers[1] = 1;
+        numbers[49] = 49;
+        numbers[99] = 99;
+    }
+
+    public static void main(String[] args) {
+        System.out.println("Hello!");
+        for (int i = 0; i < 10; i++) {
+            allocate();
+            try {
+                Thread.sleep(200);
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/PrintDateAndTime.java	Fri Aug 22 18:35:41 2014 -0400
@@ -0,0 +1,28 @@
+import java.util.Calendar;
+
+public class PrintDateAndTime {
+
+    public static void doStuff() {
+        Calendar currentCalendar = Calendar.getInstance();
+        String date = "";
+        date = date + currentCalendar.get(Calendar.YEAR) + "-";
+        date = date + (currentCalendar.get(Calendar.MONTH) + 1) + "-";
+        date = date + currentCalendar.get(Calendar.DATE);
+
+        String time = "";
+        time = time + currentCalendar.get(Calendar.HOUR) + ":";
+        time = time + currentCalendar.get(Calendar.MINUTE) + ":";
+        time = time + currentCalendar.get(Calendar.SECOND);
+
+        System.out.println(date + " " + time);
+    }
+
+    public static void doNothing() {
+        /* what do you expect from reading the method name? */
+    }
+
+    public static void main(String[] args) {
+        doNothing();
+        doStuff();
+    }
+}