Commit 4a14c7c5 authored by Lukáš Marek's avatar Lukáš Marek

Content of the instrumentation jar is automatically excluded from instrumentation

parent a293c368
......@@ -130,4 +130,28 @@
<delete dir="${build.afterbootstrap}" />
</target>
<!-- *** test instrumentaion package *** -->
<target name="check-test-property">
<condition property="test.set">
<isset property="test.name"/>
</condition>
</target>
<target name="report-missing-property" depends="check-test-property" unless="test.set">
<fail message="Property test.name is not set. Set it using -Dtest.name=value" />
</target>
<property name="test.path" value="ch/usi/dag/disl/test/${test.name}"/>
<target name="package-test" depends="report-missing-property,prepare-all" description="create instrumentation package for specified test">
<mkdir dir="${build}"/>
<jar jarfile="${build}/${instr.jar.name}"
basedir="${bin}"
includes="${test.path}/*"
excludes="${test.path}/TargetClass*.class ${test.path}/MANIFEST.MF"
manifest="${src.test}/${test.path}/MANIFEST.MF">
</jar>
</target>
</project>
......@@ -22,7 +22,9 @@ DISL_CLASS="./bin/ch/usi/dag/disl/test/$1/DiSLClass.class"
TARGET_CLASS="ch.usi.dag.disl.test.$1.TargetClass"
# start server and take pid
./runServer.sh -Ddisl.classes=${DISL_CLASS}
# suppress output
ant package-test -Dtest.name=$1 > /dev/null
./runServer.sh
# wait for server startup
sleep 3
......
......@@ -7,7 +7,9 @@ import java.security.ProtectionDomain;
import ch.usi.dag.disl.DiSL;
public class Transformer implements ClassFileTransformer {
private static DiSL disl = null;
@Override
public byte [] transform (ClassLoader loader, String className,
Class <?> classBeingRedefined, ProtectionDomain protectionDomain,
......@@ -18,8 +20,13 @@ public class Transformer implements ClassFileTransformer {
try {
// do not use dynamic bypass
DiSL disl = new DiSL(false);
// init DiSL
if(disl == null) {
// false - do not use dynamic bypass
disl = new DiSL(false);
}
instrumentedClass = disl.instrument(classfileBuffer);
if(instrumentedClass != null) {
......
......@@ -4,22 +4,17 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import ch.usi.dag.disl.cbloader.ManifestHelper.ManifestInfo;
import ch.usi.dag.disl.exception.InitException;
import ch.usi.dag.disl.exception.ManifestInfoException;
public abstract class ClassByteLoader {
private static final String MANIFEST = "META-INF/MANIFEST.MF";
public static final String PROP_DISL_CLASSES = "disl.classes";
public static final String ATTR_DISL_CLASSES = "DiSL-Classes";
public static final String DISL_CLASSES_DELIM = ":";
public static final String DISL_CLASSES_EXT = ".class";
public static final char CLASS_DELIM = '.';
......@@ -51,7 +46,11 @@ public abstract class ClassByteLoader {
return result;
} catch (IOException e) {
}
catch (IOException e) {
throw new InitException(e);
}
catch (ManifestInfoException e) {
throw new InitException(e);
}
}
......@@ -61,73 +60,58 @@ public abstract class ClassByteLoader {
String classesList = System.getProperty(PROP_DISL_CLASSES);
if ( (classesList != null) && (! classesList.isEmpty()) ) {
List<InputStream> dislClasses = new LinkedList<InputStream>();
// no classes found
if ( (classesList == null) || classesList.isEmpty() ) {
return null;
}
// get streams from class names
for (String fileName : classesList.split(DISL_CLASSES_DELIM)) {
List<InputStream> dislClasses = new LinkedList<InputStream>();
File file = new File(fileName);
dislClasses.add(new FileInputStream(file));
}
for (String fileName : classesList.split(DISL_CLASSES_DELIM)) {
return dislClasses;
File file = new File(fileName);
dislClasses.add(new FileInputStream(file));
}
return dislClasses;
return null;
}
private static List<InputStream> loadClassesFromManifest()
throws IOException {
throws IOException, ManifestInfoException {
ClassLoader cl = ClassByteLoader.class.getClassLoader();
// get DiSL manifest info
ManifestInfo mi = ManifestHelper.getDiSLManifestInfo();
String classesList = getClassesListFromManifest(cl);
// no manifest found
if(mi == null) {
return null;
}
if ( (classesList != null) && (! classesList.isEmpty()) ) {
List<InputStream> dislClasses = new LinkedList<InputStream>();
String classesList = mi.getDislClasses();
for (String className : classesList.split(DISL_CLASSES_DELIM)) {
// create file name from class name
String fileName = className.replace(CLASS_DELIM, FILE_DELIM)
+ DISL_CLASSES_EXT;
dislClasses.add(cl.getResourceAsStream(fileName));
}
return dislClasses;
// empty class list in manifest
if(classesList.isEmpty()) {
return null;
}
return null;
}
private static String getClassesListFromManifest(ClassLoader classLoader)
throws IOException {
// get all manifests...
Enumeration<URL> resources = classLoader.getResources(MANIFEST);
// get streams from class names
// and find ours...
while (resources.hasMoreElements()) {
List<InputStream> dislClasses = new LinkedList<InputStream>();
Manifest manifest =
new Manifest(resources.nextElement().openStream());
Attributes attrs = manifest.getMainAttributes();
// contains disl classes
if(attrs != null) {
String dislClasses = attrs.getValue(ATTR_DISL_CLASSES);
if(dislClasses != null) {
return dislClasses;
}
}
for (String className : classesList.split(DISL_CLASSES_DELIM)) {
// create file name from class name
String fileName = className.replace(CLASS_DELIM, FILE_DELIM)
+ DISL_CLASSES_EXT;
ClassLoader cl = ClassByteLoader.class.getClassLoader();
dislClasses.add(cl.getResourceAsStream(fileName));
}
return null;
return dislClasses;
}
}
package ch.usi.dag.disl.cbloader;
import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import ch.usi.dag.disl.exception.ManifestInfoException;
public class ManifestHelper {
private static final String MANIFEST = "META-INF/MANIFEST.MF";
public static final String ATTR_DISL_CLASSES = "DiSL-Classes";
public static class ManifestInfo {
private URL resource;
private Manifest manifest;
private String dislClasses;
public ManifestInfo(URL resource, Manifest manifest, String dislClasses) {
super();
this.resource = resource;
this.manifest = manifest;
this.dislClasses = dislClasses;
}
public URL getResource() {
return resource;
}
public Manifest getManifest() {
return manifest;
}
public String getDislClasses() {
return dislClasses;
}
}
public static ManifestInfo getDiSLManifestInfo()
throws ManifestInfoException {
try {
ClassLoader cl = ManifestInfo.class.getClassLoader();
// get all manifests...
Enumeration<URL> resources = cl.getResources(MANIFEST);
// and find ours...
while (resources.hasMoreElements()) {
URL resource = resources.nextElement();
Manifest manifest = new Manifest(resource.openStream());
Attributes attrs = manifest.getMainAttributes();
// contains disl classes
if(attrs != null) {
String dislClasses = attrs.getValue(ATTR_DISL_CLASSES);
if(dislClasses != null) {
return new ManifestInfo(resource, manifest, dislClasses);
}
}
}
}
catch (IOException e) {
throw new ManifestInfoException(e);
}
return null;
}
}
package ch.usi.dag.disl.exception;
public class ExclusionPrepareException extends DiSLException {
private static final long serialVersionUID = 6842735863939924508L;
public ExclusionPrepareException() {
super();
}
public ExclusionPrepareException(String message, Throwable cause) {
super(message, cause);
}
public ExclusionPrepareException(String message) {
super(message);
}
public ExclusionPrepareException(Throwable cause) {
super(cause);
}
}
package ch.usi.dag.disl.exception;
public class ManifestInfoException extends DiSLException {
private static final long serialVersionUID = -387235365441283865L;
public ManifestInfoException() {
super();
}
public ManifestInfoException(String message, Throwable cause) {
super(message, cause);
}
public ManifestInfoException(String message) {
super(message);
}
public ManifestInfoException(Throwable cause) {
super(cause);
}
}
......@@ -2,14 +2,23 @@ package ch.usi.dag.disl.exclusion;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import ch.usi.dag.disl.exception.DiSLIOException;
import ch.usi.dag.disl.cbloader.ManifestHelper;
import ch.usi.dag.disl.cbloader.ManifestHelper.ManifestInfo;
import ch.usi.dag.disl.exception.ExclusionPrepareException;
import ch.usi.dag.disl.exception.ManifestInfoException;
import ch.usi.dag.disl.exception.ScopeParserException;
import ch.usi.dag.disl.scope.Scope;
import ch.usi.dag.disl.scope.ScopeImpl;
import ch.usi.dag.disl.util.Constants;
public abstract class ExclusionSet {
......@@ -17,8 +26,15 @@ public abstract class ExclusionSet {
private static final String excListPath =
System.getProperty(PROP_EXCLIST, null);
public static Set<Scope> prepare() throws DiSLIOException,
ScopeParserException {
private static final String JAR_PATH_BEGIN = "/";
private static final String JAR_PATH_END = "!";
private static final char JAR_ENTRY_DELIM = '/';
private static final char CLASS_DELIM = '.';
private static final String ALL_METHODS = ".*";
public static Set<Scope> prepare() throws ScopeParserException,
ManifestInfoException, ExclusionPrepareException {
Set<Scope> exclSet = defaultExcludes();
exclSet.addAll(instrumentationJar());
......@@ -29,16 +45,23 @@ public abstract class ExclusionSet {
private static Set<Scope> defaultExcludes() throws ScopeParserException {
// if appended to the package name (for scoping purposes),
// excludes all methods in all classes in the package and sub-packages
final String EXCLUDE_CLASSES = ".*.*";
Set<Scope> exclSet = new HashSet<Scope>();
// DiSL agent classes
exclSet.add(new ScopeImpl("ch.usi.dag.dislagent.*.*"));
exclSet.add(new ScopeImpl(
"ch.usi.dag.dislagent" + EXCLUDE_CLASSES));
// dynamic bypass classes
exclSet.add(new ScopeImpl("ch.usi.dag.disl.dynamicbypass.*.*"));
exclSet.add(new ScopeImpl(
"ch.usi.dag.disl.dynamicbypass" + EXCLUDE_CLASSES));
// java instrument classes could cause troubles if instrumented
exclSet.add(new ScopeImpl("sun.instrument.*.*"));
exclSet.add(new ScopeImpl(
"sun.instrument" + EXCLUDE_CLASSES));
// TODO jb - rally has to be excluded ?
// finalize method in java.lang.Object can cause problems
......@@ -47,17 +70,75 @@ public abstract class ExclusionSet {
return exclSet;
}
private static Set<Scope> instrumentationJar() {
Set<Scope> exclSet = new HashSet<Scope>();
private static Set<Scope> instrumentationJar()
throws ManifestInfoException, ExclusionPrepareException,
ScopeParserException {
try {
// TODO jb ! add classes from instrumentation jar
// add classes from instrumentation jar
Set<Scope> exclSet = new HashSet<Scope>();
// get DiSL manifest info
ManifestInfo mi = ManifestHelper.getDiSLManifestInfo();
// no manifest found
if(mi == null) {
return exclSet;
}
// get URL of the instrumentation jar manifest
URL manifestURL =
ManifestHelper.getDiSLManifestInfo().getResource();
// manifest path contains "file:" + jar name + "!" + manifest path
String manifestPath = manifestURL.getPath();
// extract jar path
int jarPathBegin = manifestPath.indexOf(JAR_PATH_BEGIN);
int jarPathEnd = manifestPath.indexOf(JAR_PATH_END);
String jarPath = manifestPath.substring(jarPathBegin, jarPathEnd);
// open jar...
JarFile jarFile = new JarFile(jarPath);
// ... and iterate over items
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
// get entry name
String entryName = entry.getName();
// add all classes to the exclusion list
if (entryName.endsWith(Constants.CLASS_EXT)) {
String className =
entryName.replace(JAR_ENTRY_DELIM, CLASS_DELIM);
// remove class ext
int classNameEnd =
className.lastIndexOf(Constants.CLASS_EXT);
className = className.substring(0, classNameEnd);
// add exclusion for all methods
String classExcl = className + ALL_METHODS;
exclSet.add(new ScopeImpl(classExcl));
}
}
return exclSet;
return exclSet;
} catch(IOException e) {
throw new ExclusionPrepareException(e);
}
}
private static Set<Scope> readExlusionList() throws DiSLIOException,
ScopeParserException {
private static Set<Scope> readExlusionList()
throws ExclusionPrepareException, ScopeParserException {
final String COMMENT_START = "#";
......@@ -85,7 +166,7 @@ public abstract class ExclusionSet {
return exclSet;
} catch(FileNotFoundException e) {
throw new DiSLIOException(e);
throw new ExclusionPrepareException(e);
}
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment