use of javassist.NotFoundException in project compss by bsc-wdc.
the class ITAppModifier method modify.
/**
* Modify method
*
* @param appName
* @return
* @throws NotFoundException
* @throws CannotCompileException
* @throws ClassNotFoundException
*/
public Class<?> modify(String appName) throws NotFoundException, CannotCompileException, ClassNotFoundException {
Class<?> annotItf = Class.forName(appName + LoaderConstants.ITF_SUFFIX);
// Methods declared in the annotated interface
Method[] remoteMethods = annotItf.getMethods();
/*
* Use the application editor to include the COMPSs API calls on the application code
*/
CLASS_POOL.importPackage(LoaderConstants.PACKAGE_COMPSS_ROOT);
CLASS_POOL.importPackage(LoaderConstants.PACKAGE_COMPSS_API);
CLASS_POOL.importPackage(LoaderConstants.PACKAGE_COMPSS_API_IMPL);
CLASS_POOL.importPackage(LoaderConstants.PACKAGE_COMPSS_LOADER);
CLASS_POOL.importPackage(LoaderConstants.PACKAGE_COMPSS_LOADER_TOTAL);
CtClass appClass = CLASS_POOL.get(appName);
CtClass itApiClass = CLASS_POOL.get(LoaderConstants.CLASS_COMPSSRUNTIME_API);
CtClass itSRClass = CLASS_POOL.get(LoaderConstants.CLASS_STREAM_REGISTRY);
CtClass itORClass = CLASS_POOL.get(LoaderConstants.CLASS_OBJECT_REGISTRY);
CtClass appIdClass = CLASS_POOL.get(LoaderConstants.CLASS_APP_ID);
String varName = LoaderUtils.randomName(5, LoaderConstants.STR_COMPSS_PREFIX);
String itApiVar = varName + LoaderConstants.STR_COMPSS_API;
String itSRVar = varName + LoaderConstants.STR_COMPSS_STREAM_REGISTRY;
String itORVar = varName + LoaderConstants.STR_COMPSS_OBJECT_REGISTRY;
String itAppIdVar = varName + LoaderConstants.STR_COMPSS_APP_ID;
CtField itApiField = new CtField(itApiClass, itApiVar, appClass);
CtField itSRField = new CtField(itSRClass, itSRVar, appClass);
CtField itORField = new CtField(itORClass, itORVar, appClass);
CtField appIdField = new CtField(appIdClass, itAppIdVar, appClass);
itApiField.setModifiers(Modifier.PRIVATE | Modifier.STATIC);
itSRField.setModifiers(Modifier.PRIVATE | Modifier.STATIC);
itORField.setModifiers(Modifier.PRIVATE | Modifier.STATIC);
appIdField.setModifiers(Modifier.PRIVATE | Modifier.STATIC);
appClass.addField(itApiField);
appClass.addField(itSRField);
appClass.addField(itORField);
appClass.addField(appIdField);
/*
* Create a static constructor to initialize the runtime Create a shutdown hook to stop the runtime before the
* JVM ends
*/
manageStartAndStop(appClass, itApiVar, itSRVar, itORVar);
/*
* Create IT App Editor
*/
// Candidates to be instrumented if they are not
CtMethod[] instrCandidates = appClass.getDeclaredMethods();
// remote
ITAppEditor itAppEditor = new ITAppEditor(remoteMethods, instrCandidates, itApiVar, itSRVar, itORVar, itAppIdVar, appClass);
// itAppEditor.setAppId(itAppIdVar);
// itAppEditor.setAppClass(appClass);
/*
* Create Code Converter
*/
CodeConverter converter = new CodeConverter();
CtClass arrayWatcher = CLASS_POOL.get(LoaderConstants.CLASS_ARRAY_ACCESS_WATCHER);
CodeConverter.DefaultArrayAccessReplacementMethodNames names = new CodeConverter.DefaultArrayAccessReplacementMethodNames();
converter.replaceArrayAccess(arrayWatcher, (CodeConverter.ArrayAccessReplacementMethodNames) names);
/*
* Find the methods declared in the application class that will be instrumented - Main - Constructors - Methods
* that are not in the remote list
*/
if (DEBUG) {
LOGGER.debug("Flags: ToFile: " + WRITE_TO_FILE + " isWS: " + IS_WS_CLASS + " isMainClass: " + IS_MAIN_CLASS);
}
for (CtMethod m : instrCandidates) {
if (LoaderUtils.checkRemote(m, remoteMethods) == null) {
// Not a remote method, we must instrument it
if (DEBUG) {
LOGGER.debug("Instrumenting method " + m.getName());
}
StringBuilder toInsertBefore = new StringBuilder();
StringBuilder toInsertAfter = new StringBuilder();
/*
* Add local variable to method representing the execution id, which will be the current thread id. Used
* for Services, to handle multiple service executions simultaneously with a single runtime For normal
* applications, there will be only one execution id.
*/
m.addLocalVariable(itAppIdVar, appIdClass);
toInsertBefore.append(itAppIdVar).append(" = new Long(Thread.currentThread().getId());");
// TODO remove old code:
// boolean isMainProgram = writeToFile ? LoaderUtils.isOrchestration(m) : LoaderUtils.isMainMethod(m);
boolean isMainProgram = LoaderUtils.isMainMethod(m);
boolean isOrchestration = LoaderUtils.isOrchestration(m);
if (isMainProgram && IS_MAIN_CLASS) {
LOGGER.debug("Inserting calls at the beginning and at the end of main");
if (IS_WS_CLASS) {
//
LOGGER.debug("Inserting calls noMoreTasks at the end of main");
toInsertAfter.insert(0, itApiVar + ".noMoreTasks(" + itAppIdVar + ", true);");
m.insertBefore(toInsertBefore.toString());
// executed only if Orchestration finishes properly
m.insertAfter(toInsertAfter.toString());
} else {
// Main program
LOGGER.debug("Inserting calls noMoreTasks and stopIT at the end of main");
// Set global variable for main as well, will be used in code inserted after to be run no matter
// what
toInsertBefore.append(appName).append('.').append(itAppIdVar).append(" = new Long(Thread.currentThread().getId());");
// toInsertAfter.append("System.exit(0);");
toInsertAfter.insert(0, itApiVar + ".stopIT(true);");
toInsertAfter.insert(0, itApiVar + ".noMoreTasks(" + appName + '.' + itAppIdVar + ", true);");
m.insertBefore(toInsertBefore.toString());
// executed no matter what
m.insertAfter(toInsertAfter.toString(), true);
}
/*
* Instrumenting first the array accesses makes each array access become a call to a black box
* method of class ArrayAccessWatcher, whose parameters include the array. For the second round of
* instrumentation, the synchronization by transition to black box automatically synchronizes the
* arrays accessed. TODO: Change the order of instrumentation, so that we have more control about
* the synchronization, and we can distinguish between a write access and a read access (now it's
* read/write access by default, because it goes into the black box).
*/
m.instrument(converter);
m.instrument(itAppEditor);
} else if (isOrchestration) {
if (IS_WS_CLASS) {
//
LOGGER.debug("Inserting calls noMoreTasks and stopIT at the end of orchestration");
toInsertAfter.insert(0, itApiVar + ".noMoreTasks(" + itAppIdVar + ", true);");
m.insertBefore(toInsertBefore.toString());
// executed only if Orchestration finishes properly
m.insertAfter(toInsertAfter.toString());
} else {
LOGGER.debug("Inserting only before at the beginning of an orchestration");
m.insertBefore(toInsertBefore.toString());
// TODO remove old code m.insertAfter(toInsertAfter.toString());
// executed only if Orchestration finishes properly
}
m.instrument(converter);
m.instrument(itAppEditor);
} else {
LOGGER.debug("Inserting only before");
m.insertBefore(toInsertBefore.toString());
if (IS_WS_CLASS) {
// non-OE operations
if (Modifier.isPrivate(m.getModifiers())) {
m.instrument(converter);
m.instrument(itAppEditor);
}
} else {
// For an application class, instrument all non-remote methods
m.instrument(converter);
m.instrument(itAppEditor);
}
}
}
}
// Instrument constructors
for (CtConstructor c : appClass.getDeclaredConstructors()) {
if (DEBUG) {
LOGGER.debug("Instrumenting constructor " + c.getLongName());
}
c.instrument(converter);
c.instrument(itAppEditor);
}
if (WRITE_TO_FILE) {
// Write the modified class to disk
try {
appClass.writeFile();
} catch (Exception e) {
ErrorManager.fatal("Error writing the instrumented class file");
}
return null;
} else {
/*
* Load the modified class into memory and return it. Generally, once a class is loaded into memory no
* further modifications can be performed on it.
*/
return appClass.toClass();
}
}
use of javassist.NotFoundException in project compss by bsc-wdc.
the class ITAppEditor method replaceBlackBox.
/**
* Replaces the blackBox calls
*
* @return
*/
private String replaceBlackBox(String methodName, String className, CtMethod method) throws CannotCompileException {
if (DEBUG) {
LOGGER.debug("Inspecting method call to black-box method " + methodName + ", looking for objects");
}
StringBuilder modifiedCall = new StringBuilder();
StringBuilder toSerialize = new StringBuilder();
// Check if the black-box we're going to is one of the array watch methods
boolean isArrayWatch = method.getDeclaringClass().getName().equals(LoaderConstants.CLASS_ARRAY_ACCESS_WATCHER);
// First check the target object
modifiedCall.append(itORVar).append(NEW_OBJECT_ACCESS + "$0);");
toSerialize.append(itORVar).append(SERIALIZE_LOCALLY + "$0);");
/*
* Now add the call. If the target object of the call is a task object, invoke the method on the internal object
* stored by the runtime. Also check the parameters. We need to control the parameters of non-remote and
* non-instrumented methods (black box), since they represent the border to the code where we can't intercept
* anything. If any of these parameters is an object we kept track of, synchronize
*/
String redirectedCallPars = null;
try {
CtClass[] paramTypes = method.getParameterTypes();
if (paramTypes.length > 0) {
int i = 1;
StringBuilder aux1 = new StringBuilder("new Object[] {");
for (CtClass parType : paramTypes) {
if (i > 1) {
aux1.append(',');
/* aux2.append(','); */
}
String parId = "$" + i;
if (parType.isPrimitive()) {
if (parType.equals(CtClass.booleanType)) {
aux1.append("new Boolean(").append(parId).append(')');
} else if (parType.equals(CtClass.charType)) {
aux1.append("new Character(").append(parId).append(')');
} else if (parType.equals(CtClass.byteType)) {
aux1.append("new Byte(").append(parId).append(')');
} else if (parType.equals(CtClass.shortType)) {
aux1.append("new Short(").append(parId).append(')');
} else if (parType.equals(CtClass.intType)) {
aux1.append("new Integer(").append(parId).append(')');
} else if (parType.equals(CtClass.longType)) {
aux1.append("new Long(").append(parId).append(')');
} else if (parType.equals(CtClass.floatType)) {
aux1.append("new Float(").append(parId).append(')');
} else {
// if (parType.equals(CtClass.doubleType))
aux1.append("new Double(").append(parId).append(')');
}
} else if (parType.getName().equals(String.class.getName())) {
// This is a string
if (DEBUG) {
LOGGER.debug("Parameter " + i + " of black-box method " + methodName + " is an String, adding File/object access");
}
if (isArrayWatch && i == 3) {
// Prevent from synchronizing task return objects to be stored in an array position
aux1.append(parId);
} else {
String calledClass = className;
if (calledClass.equals(PrintStream.class.getName()) || calledClass.equals(StringBuilder.class.getName())) {
// If the call is inside a PrintStream or StringBuilder, only synchronize objects files
// already has the name
String internalObject = itORVar + GET_INTERNAL_OBJECT + parId + ')';
modifiedCall.insert(0, itORVar + NEW_OBJECT_ACCESS + parId + ");");
aux1.append(internalObject).append(" == null ? ").append(parId).append(" : ").append("(" + parType.getName() + ")").append(internalObject);
toSerialize.append(itORVar).append(SERIALIZE_LOCALLY).append(parId).append(");");
} else {
String internalObject = itORVar + GET_INTERNAL_OBJECT + parId + ')';
String taskFile = itSRVar + IS_TASK_FILE + parId + ")";
String apiOpenFile = itApiVar + OPEN_FILE + parId + ", " + DATA_DIRECTION + ".INOUT)";
modifiedCall.insert(0, itORVar + NEW_OBJECT_ACCESS + parId + ");");
// Adding check of task files
aux1.append(taskFile).append(" ? ").append(apiOpenFile).append(" : ").append(internalObject).append(" == null ? ").append(parId).append(" : ").append("(" + parType.getName() + ")").append(internalObject);
toSerialize.append(itORVar).append(SERIALIZE_LOCALLY).append(parId).append(");");
}
}
} else {
// Object (also array)
if (DEBUG) {
LOGGER.debug("Parameter " + i + " of black-box method " + methodName + " is an object, adding access");
}
if (isArrayWatch && i == 3) {
// Prevent from synchronizing task return objects to be stored in an array position
aux1.append(parId);
} else {
String internalObject = itORVar + GET_INTERNAL_OBJECT + parId + ')';
modifiedCall.insert(0, itORVar + NEW_OBJECT_ACCESS + parId + ");");
aux1.append(internalObject).append(" == null ? ").append(parId).append(" : ").append("(" + parType.getName() + ")").append(internalObject);
toSerialize.append(itORVar).append(SERIALIZE_LOCALLY).append(parId).append(");");
}
}
i++;
}
aux1.append("}");
redirectedCallPars = aux1.toString();
}
} catch (NotFoundException e) {
throw new CannotCompileException(e);
}
String internalObject = itORVar + GET_INTERNAL_OBJECT + "$0)";
modifiedCall.append("if (").append(internalObject).append(" != null) {").append("$_ = ($r)" + RUN_METHOD_ON_OBJECT).append(internalObject).append(",$class,\"").append(methodName).append("\",").append(redirectedCallPars).append(",$sig);").append("}else { $_ = ($r)" + RUN_METHOD_ON_OBJECT + "$0,$class,\"").append(methodName).append("\",").append(redirectedCallPars).append(",$sig); }");
// Serialize the (internal) objects locally after the call
modifiedCall.append(toSerialize);
// Return all the modified call
return modifiedCall.toString();
}
use of javassist.NotFoundException in project compss by bsc-wdc.
the class ITAppEditor method replaceAPICall.
/**
* Replaces the API calls
*
* @return
* @throws NotFoundException
*/
private String replaceAPICall(String methodName, CtMethod method) throws CannotCompileException {
boolean isVoid = false;
boolean hasArgs = false;
try {
Class<?> retType = method.getReturnType().getClass();
isVoid = retType.equals(void.class);
hasArgs = (method.getParameterTypes().length != 0);
} catch (NotFoundException e) {
throw new CannotCompileException(e);
}
// Add the COMPSsRuntime API Call with the given appId ALWAYS as FIRST parameter
// Something like: itApiVar.methodName(itAppIdVar, $$);
StringBuilder apiCall = new StringBuilder("");
if (isVoid) {
apiCall.append("$_ = ").append(itApiVar);
} else {
apiCall.append(itApiVar);
}
apiCall.append(".").append(methodName).append("(").append(itAppIdVar);
if (hasArgs) {
apiCall.append(", $$");
} else {
// Nothing to add
}
apiCall.append(");");
return apiCall.toString();
}
use of javassist.NotFoundException in project fakereplace by fakereplace.
the class MainTransformer method transform.
@Override
public byte[] transform(final ClassLoader loader, final String className, final Class<?> classBeingRedefined, final ProtectionDomain protectionDomain, final byte[] classfileBuffer) throws IllegalClassFormatException {
if (className == null) {
// TODO: deal with lambdas
return classfileBuffer;
}
boolean replaceable = Fakereplace.isClassReplaceable(className, loader);
if (classBeingRedefined != null) {
retransformationStarted = true;
if (logClassRetransformation && replaceable) {
log.info("Fakereplace is replacing class " + className);
}
}
ChangedClassImpl changedClass = null;
if (classBeingRedefined != null) {
changedClass = new ChangedClassImpl(classBeingRedefined);
}
boolean changed = false;
if (!replaceable && UnmodifiedFileIndex.isClassUnmodified(className)) {
return null;
}
Set<Class<?>> classesToRetransform = new HashSet<>();
final ClassFile file;
try {
Set<MethodInfo> modifiedMethods = new HashSet<>();
file = new ClassFile(new DataInputStream(new ByteArrayInputStream(classfileBuffer)));
for (final FakereplaceTransformer transformer : transformers) {
if (transformer.transform(loader, className, classBeingRedefined, protectionDomain, file, classesToRetransform, changedClass, modifiedMethods)) {
changed = true;
}
}
if (!changed) {
UnmodifiedFileIndex.markClassUnmodified(className);
return null;
} else {
try {
if (!modifiedMethods.isEmpty()) {
ClassPool classPool = new ClassPool();
if (loader == null) {
classPool.appendClassPath(new LoaderClassPath(ClassLoader.getSystemClassLoader()));
} else {
classPool.appendClassPath(new LoaderClassPath(loader));
}
classPool.appendSystemPath();
for (MethodInfo method : modifiedMethods) {
if (method.getCodeAttribute() != null) {
method.getCodeAttribute().computeMaxStack();
try {
method.rebuildStackMap(classPool);
} catch (BadBytecode e) {
Throwable root = e;
while (!(root instanceof NotFoundException) && root != null && root.getCause() != root) {
root = root.getCause();
}
if (root instanceof NotFoundException) {
NotFoundException cause = (NotFoundException) root;
Bytecode bytecode = new Bytecode(file.getConstPool());
bytecode.addNew(NoClassDefFoundError.class.getName());
bytecode.add(Opcode.DUP);
bytecode.addLdc(cause.getMessage());
bytecode.addInvokespecial(NoClassDefFoundError.class.getName(), "<init>", "(Ljava/lang/String;)V");
bytecode.add(Opcode.ATHROW);
method.setCodeAttribute(bytecode.toCodeAttribute());
method.getCodeAttribute().computeMaxStack();
method.getCodeAttribute().setMaxLocals(DescriptorUtils.maxLocalsFromParameters(method.getDescriptor()) + 1);
method.rebuildStackMap(classPool);
} else {
throw e;
}
}
}
}
}
} catch (BadBytecode e) {
throw new RuntimeException(e);
}
ByteArrayOutputStream bs = new ByteArrayOutputStream();
file.write(new DataOutputStream(bs));
// dump the class for debugging purposes
final String dumpDir = AgentOptions.getOption(AgentOption.DUMP_DIR);
if (dumpDir != null) {
try {
File dump = new File(dumpDir + '/' + file.getName() + ".class");
dump.getParentFile().mkdirs();
FileOutputStream s = new FileOutputStream(dump);
DataOutputStream dos = new DataOutputStream(s);
file.write(dos);
s.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (!classesToRetransform.isEmpty()) {
synchronized (this) {
retransformationOutstandingCount++;
}
Thread t = new Thread(() -> {
try {
Fakereplace.getInstrumentation().retransformClasses(classesToRetransform.toArray(new Class[classesToRetransform.size()]));
} catch (UnmodifiableClassException e) {
log.error("Failed to retransform classes", e);
} finally {
synchronized (MainTransformer.this) {
retransformationOutstandingCount--;
notifyAll();
}
}
});
t.setDaemon(true);
t.start();
}
if (classBeingRedefined != null) {
changedClasses.add(changedClass);
queueIntegration();
}
return bs.toByteArray();
}
} catch (IOException e) {
e.printStackTrace();
throw new IllegalClassFormatException(e.getMessage());
} catch (Throwable e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
use of javassist.NotFoundException in project javaparser by javaparser.
the class JavassistClassDeclaration method solveMethod.
@Deprecated
public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> argumentsTypes, boolean staticOnly) {
List<ResolvedMethodDeclaration> candidates = new ArrayList<>();
Predicate<CtMethod> staticOnlyCheck = m -> !staticOnly || (staticOnly && Modifier.isStatic(m.getModifiers()));
for (CtMethod method : ctClass.getDeclaredMethods()) {
boolean isSynthetic = method.getMethodInfo().getAttribute(SyntheticAttribute.tag) != null;
boolean isNotBridge = (method.getMethodInfo().getAccessFlags() & AccessFlag.BRIDGE) == 0;
if (method.getName().equals(name) && !isSynthetic && isNotBridge && staticOnlyCheck.test(method)) {
candidates.add(new JavassistMethodDeclaration(method, typeSolver));
}
}
try {
CtClass superClass = ctClass.getSuperclass();
if (superClass != null) {
SymbolReference<ResolvedMethodDeclaration> ref = new JavassistClassDeclaration(superClass, typeSolver).solveMethod(name, argumentsTypes, staticOnly);
if (ref.isSolved()) {
candidates.add(ref.getCorrespondingDeclaration());
}
}
} catch (NotFoundException e) {
throw new RuntimeException(e);
}
try {
for (CtClass interfaze : ctClass.getInterfaces()) {
SymbolReference<ResolvedMethodDeclaration> ref = new JavassistInterfaceDeclaration(interfaze, typeSolver).solveMethod(name, argumentsTypes, staticOnly);
if (ref.isSolved()) {
candidates.add(ref.getCorrespondingDeclaration());
}
}
} catch (NotFoundException e) {
throw new RuntimeException(e);
}
return MethodResolutionLogic.findMostApplicable(candidates, name, argumentsTypes, typeSolver);
}
Aggregations