Commit caed92ea authored by Aibek Sarimbekov's avatar Aibek Sarimbekov

Added recasted jcarder

parent 9d9aee0d
<project name="disl-test" default="compile" basedir=".">
<property file="../../disl.version"/>
<property file="../../build.properties"/>
<property file="build.properties"/>
<property name="disl.jar.path" value="../../build/dislserver-${disl.version}.jar"/>
<path id="buildpath">
<pathelement location="${disl.jar.path}"/>
<pathelement location="../../${asm.path}"/>
</path>
<target name="check-disl-jar">
<available file="${disl.jar.path}" property="disl.jar.present"/>
</target>
<target name="report-missing-jar" depends="check-disl-jar" unless="disl.jar.present">
<fail message="DiSL jar not found at ${disl.jar.path}. Build DiSL first!" />
</target>
<target name="compile" depends="report-missing-jar">
<mkdir dir="bin"/>
<javac srcdir="src" destdir="bin" debug="true" includeAntRuntime="false">
<classpath refid="buildpath"/>
</javac>
</target>
<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/example/${test.name}"/>
<target name="package" depends="report-missing-property,compile" description="create instrumentation package for specified test">
<jar jarfile="../../build/${instr.jar.name}"
basedir="./bin"
includes="${test.path}/**"
excludes="${test.path}/TargetClass*.class ${test.path}/MANIFEST.MF"
manifest="./src/${test.path}/MANIFEST.MF">
</jar>
</target>
<target name="clean">
<delete dir="bin"/>
<delete dir="build"/>
</target>
</project>
# THESE ARE THE BASIC SETTINGS
sun.instrument.*.*
ch.usi.dag.disl.example.*.*
# THESE ARE THE RUNTIME CLASSES THAT MUST NOT BE WOVEN
# PROBLEM WITH FOP (CODE TOO BIG)
# BEGIN JDK WEAVING
# COMMENT THE FOLLOWING FOR FULL COVERAGE
#org.jcp.*
#org.omg.*
#org.xml.*
#org.ietf.*
javax.*.*
java.*.*
com.sun.*.*
com.apple.*.*
sun.*.*
sunx.*.*
# END JDK
# /bin/sh
EXPECTED_ARGS=1
if [ $# -gt $EXPECTED_ARGS ]
then
echo "Usage: `basename $0` [pkg]"
exit
fi
SERVER_FILE=.server.pid
export SERVER_FILE
if [ -e ${SERVER_FILE} ]
then
kill -KILL `cat ${SERVER_FILE}`
rm .server.pid
fi
DISL_CLASS="./bin/ch/usi/dag/disl/example/jcarder/DiSLClass.class"
TARGET_CLASS="ch.usi.dag.disl.example.jcarder.TargetClass"
if [ "$1" = "pkg" ]
then
# start server and take pid
ant package -Dtest.name=jcarder
./runServer.sh
else
# start server and take pid
./runServer.sh -Ddisl.classes=${DISL_CLASS}
fi
# wait for server startup
sleep 5
# run client
./runClient.sh ${TARGET_CLASS}
# kill server
kill -KILL `cat ${SERVER_FILE}`
rm .server.pid
#!/bin/bash
OS=`uname`
if [ "${OS}" = "Darwin" ]; then
C_AGENT="../../src-agent-c/libdislagent.jnilib"
else
C_AGENT="../../src-agent-c/libdislagent.so"
fi
all=' apparat actors'
iall=`java -jar /Users/aibeksarimbekov/Software/scala-benchmark.jar -l`
iiall=' apparat actors batik dummy factorie h2 jython kiama scalac scaladoc scalap scalariform scalatest scalaxb specs sunflow tmt xalan '
for bench in ${all}
do
echo Starting $bench
java -Xmx2g -XX:MaxPermSize=128m -noverify -agentpath:${C_AGENT} -javaagent:../../build/dislagent-unspec.jar \
-Xbootclasspath/a:../../build/dislagent-unspec.jar:../../build/dislinstr.jar \
-cp bin/ \
-jar /Users/aibeksarimbekov/Software/scala-benchmark.jar --preserve $bench
# $*
echo Finished $bench
done
#!/bin/bash
iall=`java -jar /Users/aibeksarimbekov/Software/dacapo-9.12-bach.jar -l`
all='
avrora
batik
eclipse
fop
h2
jython
luindex
lusearch
pmd
sunflow
tomcat
tradebeans
tradesoap
xalan
'
for bench in ${all}
do
./run.sh $bench
done
#!/bin/sh
# available options
# -Ddebug=true \
# -Ddisl.classes="list of disl classes (: - separator)"
# -Ddisl.noexcepthandler=true \
# -Ddisl.exclusionList="path" \
# -Ddislserver.instrumented="path" \
# -Ddislserver.uninstrumented="path" \
# -Ddislserver.port="portNum" \
# -Ddislserver.timestat=true \
# -Ddislserver.continuous=true \
java $* \
-Ddislserver.instrumented="instrumented" \
-Ddebug=false \
-Ddislserver.uninstrumented="uninstrumented" \
-Ddislserver.continuous=true \
-Ddisl.exclusionList="conf/exclusion.lst" \
-jar ../../build/dislserver-unspec.jar \
&
echo $! > ${SERVER_FILE}
package ch.usi.dag.disl.example.jcarder;
import ch.usi.dag.disl.annotation.Before;
import ch.usi.dag.disl.annotation.SyntheticLocal;
import ch.usi.dag.disl.dynamiccontext.DynamicContext;
import ch.usi.dag.disl.example.jcarder.runtime.JCarderAnalysis;
import ch.usi.dag.disl.marker.BytecodeMarker;
import ch.usi.dag.disl.staticcontext.MethodStaticContext;
public class DiSLClass {
@SyntheticLocal
static boolean lockOnThis = false;
@Before(marker = BytecodeMarker.class, args = "monitorenter", guard = NotThread.class)
public static void onMonitorEnter(MethodStaticContext sc, DynamicContext dc) {
String mClassAndMethodName = sc.thisClassName() + "." + sc.thisMethodName()+ "()";
if(dc.getStackValue(0, Object.class) == dc.getThis())
lockOnThis = true;
JCarderAnalysis.instanceOf().onMonitorEnter(dc.getStackValue(0, Object.class), mClassAndMethodName, lockOnThis);
}
@Before(marker = BytecodeMarker.class, args = "monitorexit", guard = NotThread.class)
public static void onMonitorExit(MethodStaticContext sc, DynamicContext dc) {
String mClassAndMethodName = sc.thisClassName() + "." + sc.thisMethodName()+ "()";
if(dc.getStackValue(0, Object.class) == dc.getThis())
lockOnThis = true;
JCarderAnalysis.instanceOf().onMonitorExit(dc.getStackValue(0, Object.class), mClassAndMethodName, lockOnThis);
}
}
Manifest-Version: 1.0
DiSL-Classes: ch.usi.dag.disl.example.jcarder.DiSLClass
DiSL-Transformer: ch.usi.dag.disl.example.jcarder.SynchronizedMethodsTransformer
\ No newline at end of file
package ch.usi.dag.disl.example.jcarder;
import ch.usi.dag.disl.staticcontext.MethodStaticContext;
public class MyMethodStaticContext extends MethodStaticContext {
}
package ch.usi.dag.disl.example.jcarder;
import ch.usi.dag.disl.annotation.GuardMethod;
import ch.usi.dag.disl.staticcontext.MethodStaticContext;
public class NotThread {
@GuardMethod
public static boolean isApplicable(MethodStaticContext msc) {
return !msc.thisClassName().equals("java/lang/Thread");
}
}
package ch.usi.dag.disl.example.jcarder;
import ch.usi.dag.disl.annotation.GuardMethod;
import ch.usi.dag.disl.staticcontext.MethodStaticContext;
public class OnlySynchronized {
@GuardMethod
public static boolean isApplicable(MethodStaticContext msc) {
return msc.isMethodSynchronized();
}
}
package ch.usi.dag.disl.example.jcarder;
import ch.usi.dag.disl.annotation.GuardMethod;
import ch.usi.dag.disl.guardcontext.GuardContext;
public class OnlySynchronizedAndNotThread {
@GuardMethod
public static boolean isApplicable(GuardContext gc) {
return gc.invoke(NotThread.class) && gc.invoke(OnlySynchronized.class);
}
}
package ch.usi.dag.disl.example.jcarder;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.LdcInsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.TryCatchBlockNode;
import org.objectweb.asm.tree.VarInsnNode;
import ch.usi.dag.disl.transformer.Transformer;
import ch.usi.dag.disl.util.Constants;
import ch.usi.dag.dislserver.DiSLServerException;
public class SynchronizedMethodsTransformer implements Transformer {
final private static String instrPath = "transformed";
final private static String CLASS_EXT = ".class";
final private static char PACKAGE_STD_DELIM = '.';
final private static boolean DEBUG = false;
@Override
public byte[] transform(byte[] classfileBuffer) throws Exception {
byte[] instrumentedBytes = null;
ClassReader cr = new ClassReader(classfileBuffer);
ClassNode clazz = new ClassNode(Opcodes.ASM4);
cr.accept(clazz, 0);
if(clazz.name.startsWith("java")
|| clazz.name.startsWith("sun")
//|| clazz.name.contains("disl")
|| clazz.name.contains("com")
) {
return classfileBuffer;
}
String className = clazz.name.replace('/', '.');
for (MethodNode method : (List<MethodNode>) clazz.methods) {
boolean isStatic = false;
if ((method.access & Opcodes.ACC_ABSTRACT) != 0
|| (method.access & Opcodes.ACC_NATIVE) != 0) {
continue;
}
if ((method.access & Opcodes.ACC_SYNCHRONIZED) != 0) {
if(DEBUG)
System.err.println("++++ Transfroming the method " + clazz.name +"." + method.name + " ++++");
if ((method.access & Opcodes.ACC_STATIC) != 0) {
isStatic = true;
}
method.access -= Opcodes.ACC_SYNCHRONIZED;
InsnList instructions = method.instructions;
final LabelNode startTryCatchBlockLabel = new LabelNode();
final LabelNode endTryCatchBlockLabel = new LabelNode();
InsnList myList = new InsnList();
myList.add(startTryCatchBlockLabel);
if(isStatic) {
myList.add(new LdcInsnNode(className));
myList.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
"java/lang/Class",
"forName",
"(Ljava/lang/String;)Ljava/lang/Class;"));
}
else {
myList.add(new VarInsnNode(Opcodes.ALOAD, 0));
}
myList.add(new InsnNode(Opcodes.MONITORENTER));
instructions.insert(myList);
Iterator<AbstractInsnNode> it = instructions.iterator();
while(it.hasNext()) {
AbstractInsnNode instruction = (AbstractInsnNode) it.next();
int opcode = instruction.getOpcode();
if(opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN)
{
myList.clear();
if(isStatic) {
myList.add(new LdcInsnNode(className));
myList.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
"java/lang/Class",
"forName",
"(Ljava/lang/String;)Ljava/lang/Class;"));
}
else {
myList.add(new VarInsnNode(Opcodes.ALOAD, 0));
}
myList.add(new InsnNode(Opcodes.MONITOREXIT));
instructions.insert(instruction.getPrevious(), myList);
}
}
myList.clear();
LabelNode normalExecutionFinallyBlockLabel = new LabelNode();
myList.add(endTryCatchBlockLabel);
method.tryCatchBlocks.add(new
TryCatchBlockNode(startTryCatchBlockLabel, endTryCatchBlockLabel,
endTryCatchBlockLabel, null));
if(isStatic) {
myList.add(new LdcInsnNode(className));
myList.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
"java/lang/Class",
"forName",
"(Ljava/lang/String;)Ljava/lang/Class;"));
}
else {
myList.add(new VarInsnNode(Opcodes.ALOAD, 0));
}
myList.add(new InsnNode(Opcodes.MONITOREXIT));
myList.add(new InsnNode(Opcodes.ATHROW));
myList.add(normalExecutionFinallyBlockLabel);
instructions.add(myList);
}
}
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
clazz.accept(cw);
instrumentedBytes = cw.toByteArray();
dump(clazz.name, instrumentedBytes, instrPath);
return instrumentedBytes;
}
@Override
public boolean propagateUninstrumentedClasses() {
return false;
}
private void dump(String className, byte[] codeAsBytes, String path)
throws DiSLServerException {
try {
// extract the class name and package name
int i = className.lastIndexOf(Constants.PACKAGE_INTERN_DELIM);
String onlyClassName = className.substring(i + 1);
String packageName = className.substring(0, i + 1);
// construct path to the class
String pathWithPkg = path + File.separator + packageName;
// create directories
new File(pathWithPkg).mkdirs();
// dump the class code
FileOutputStream fo = new FileOutputStream(pathWithPkg
+ onlyClassName + Constants.CLASS_EXT);
fo.write(codeAsBytes);
fo.close();
}
catch (FileNotFoundException e) {
throw new DiSLServerException(e);
}
catch (IOException e) {
throw new DiSLServerException(e);
}
}
}
package ch.usi.dag.disl.example.jcarder;
public class TargetClass {
// Object myLock = new Object();
// Object myLock2 = new Object();
//
// void fum() {
// synchronized (myLock) {
// System.err.println("Holding a lock on " + myLock.hashCode());
// }
// synchronized (myLock2) {
// System.err.println("Holding a lock on " + myLock2.hashCode());
// };
//
// }
//
// void fie() {
// synchronized (myLock2) {
// System.err.println("Holding a lock on " + myLock2.hashCode());
// };
// synchronized (myLock) {
// System.err.println("Holding a lock on " + myLock.hashCode());
// }
// }
//
// synchronized void foo() {
// fum();
// }
//
// public static void main(String args[]) {
// System.err.println("TargetClass is starting!");
// TargetClass tc = new TargetClass();
// tc.fum();
// tc.foo();
// tc.fie();
// System.err.println("TargetClass finished!");
// }
//
// public synchronized String toString() {
// return new String(new byte[3], 0, 1);
// }
// private static synchronized void writeObject(java.io.ObjectOutputStream s)
// throws java.io.IOException {
// java.io.ObjectOutputStream.PutField fields = s.putFields();
// fields.put("value", 1);
// fields.put("count", 2);
// fields.put("shared", false);
// s.writeFields();
// }
Object myLock = new Object();
void fum() {
synchronized (myLock) {
}
}
void fie() {
fum();
}
synchronized void foo() {
fie();
}
public static void main(String args[]) {
new TargetClass().foo();
}
}
/*
* JCarder -- cards Java programs to keep threads disentangled
*
* Copyright (C) 2006-2007 Enea AB
* Copyright (C) 2007 Ulrik Svensson
* Copyright (C) 2007 Joel Rosdahl
*
* This program is made available under the GNU GPL version 2, with a special
* exception for linking with JUnit. See the accompanying file LICENSE.txt for
* details.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*/
package ch.usi.dag.disl.example.jcarder.runtime;
import static ch.usi.dag.disl.example.jcarder.runtime.common.contexts.ContextFileReader.CONTEXTS_DB_FILENAME;
import static ch.usi.dag.disl.example.jcarder.runtime.common.contexts.ContextFileReader.EVENT_DB_FILENAME;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import ch.usi.dag.disl.example.jcarder.runtime.common.LockingContext;
import ch.usi.dag.disl.example.jcarder.runtime.common.contexts.ContextFileWriter;
import ch.usi.dag.disl.example.jcarder.runtime.common.contexts.ContextWriterIfc;
import ch.usi.dag.disl.example.jcarder.runtime.common.events.EventFileWriter;
import ch.usi.dag.disl.example.jcarder.runtime.common.events.LockEventListenerIfc;
import ch.usi.dag.disl.example.jcarder.runtime.util.Counter;
import ch.usi.dag.disl.example.jcarder.runtime.util.logging.Logger;
final class EventListener implements EventListenerIfc {
private final LockEventListenerIfc mLockEventListener;
private final LockIdGenerator mLockIdGenerator;
private final LockingContextIdCache mContextCache;
private final Logger mLogger;
private final Counter mNumberOfEnteredMonitors;
private final Map<Class, Object> monitorInfoCache =
new HashMap<Class, Object>();
private final List<String> filterClassLevel =
getFilterList("jcarder.classLevel", false);
private final List<String> filterInclude =
getFilterList("jcarder.include", true);
private final static Object sentinelInstanceLevel = new Object();
private final static Object sentinelIgnore = new Object();
public static EventListener create(Logger logger, File outputdir)
throws IOException {
EventFileWriter eventWriter =
new EventFileWriter(logger,
new File(outputdir, EVENT_DB_FILENAME));
ContextFileWriter contextWriter =
new ContextFileWriter(logger,
new File(outputdir, CONTEXTS_DB_FILENAME));
return new EventListener(logger, eventWriter, contextWriter);
}
private List<String> getFilterList(String key, boolean defaultAcceptAll) {
final List<String> ret = new ArrayList<String>();
final StringTokenizer tok =
new StringTokenizer(
System.getProperty(key, defaultAcceptAll ? " " : ""), ",");
while (tok.hasMoreTokens()) {
ret.add(tok.nextToken().trim());
}
return ret;
}
public EventListener(Logger logger,
LockEventListenerIfc lockEventListener,
ContextWriterIfc contextWriter) {
mLogger = logger;
mLockEventListener = lockEventListener;
mLockIdGenerator = new LockIdGenerator(mLogger, contextWriter);
mContextCache = new LockingContextIdCache(mLogger, contextWriter);
mNumberOfEnteredMonitors =
new Counter("Entered Monitors", mLogger, 100000);
}
public void beforeMonitorEnter(Object monitor, LockingContext context)
throws Exception {
mLogger.finest("EventListener.beforeMonitorEnter");
// Check ignoreFilter and switch to class level if the monitor is
// matched by classLevelFilter. Results are cached.
Object classifiedMonitor = checkMonitor(monitor);
if (classifiedMonitor != sentinelIgnore) {
mNumberOfEnteredMonitors.increment();
lockEvent(true, monitor, classifiedMonitor, context);
}
}
public void beforeMonitorExit(Object monitor, LockingContext context)
throws Exception {
mLogger.finest("EventListener.beforeMonitorExit");
// Check ignoreFilter and switch to class level if the monitor is
// matched by classLevelFilter. Results are cached.
Object classifiedMonitor = checkMonitor(monitor);
if (classifiedMonitor != sentinelIgnore) {
lockEvent(false, monitor, classifiedMonitor, context);
}
}
private Object checkMonitor(Object monitor) {
// The default behaviour is to treat monitor objects on instance level.
// This was the old behaviour.
Object classifiedMonitor = monitor;
if (monitor != null) {
final Class cl = monitor.getClass();
Object firstOccurrence;
synchronized(this) {
// Try to use cache.
firstOccurrence = monitorInfoCache.get(cl);
if (firstOccurrence == null) {
firstOccurrence = checkFilters(monitor, cl);
}
}
// firstOccurence may have three states at this point:
//
// 1. sentinelInstanceLevel: (default) The monitor should be
// handled for each instance.
// 2. sentinelIgnore: The monitor is not of interest.
// 3. Any other instance is the first representation of a monitor
// of its class. Class level handling.
if (firstOccurrence != sentinelInstanceLevel) {
// By using only one single instance for monitors of a certain
// class we simulate group level handling.
classifiedMonitor = firstOccurrence;