use of org.objectweb.asm.tree.ClassNode in project SpecialSource by md-5.
the class RuntimeRepo method findClass0.
@Override
protected ClassNode findClass0(String internalName) {
ClassReader cr;
try {
cr = new ClassReader(internalName);
} catch (Exception ex) {
return null;
}
ClassNode node = new ClassNode();
cr.accept(node, 0);
return node;
}
use of org.objectweb.asm.tree.ClassNode in project SpecialSource by md-5.
the class CachingRepo method findClass.
@Override
public final ClassNode findClass(String internalName) {
ClassNode fromCache = cache.getIfPresent(internalName);
if (fromCache != null) {
return fromCache;
}
ClassNode found = findClass0(internalName);
if (found != null) {
cache.put(internalName, found);
return found;
}
return null;
}
use of org.objectweb.asm.tree.ClassNode in project drill by apache.
the class TestClassTransformation method testScalarReplacementWithArrayAssignment.
@Test
public void testScalarReplacementWithArrayAssignment() throws Exception {
ClassTransformer.ClassNames classNames = new ClassTransformer.ClassNames("org.apache.drill.CompileClassWithArraysAssignment");
String entireClass = DrillFileUtils.getResourceAsString(DrillFileUtils.SEPARATOR + classNames.slash + ".java");
sessionOptions.setLocalOption(ClassCompilerSelector.JAVA_COMPILER_DEBUG_OPTION, false);
List<String> compilers = Arrays.asList(ClassCompilerSelector.CompilerPolicy.JANINO.name(), ClassCompilerSelector.CompilerPolicy.JDK.name());
for (String compilerName : compilers) {
sessionOptions.setLocalOption(ClassCompilerSelector.JAVA_COMPILER_OPTION, compilerName);
QueryClassLoader queryClassLoader = new QueryClassLoader(config, sessionOptions);
byte[][] implementationClasses = queryClassLoader.getClassByteCode(classNames, entireClass);
ClassNode originalClass = AsmUtil.classFromBytes(implementationClasses[0], ClassReader.EXPAND_FRAMES);
ClassNode transformedClass = new ClassNode();
DrillCheckClassAdapter mergeGenerator = new DrillCheckClassAdapter(CompilationConfig.ASM_API_VERSION, new CheckClassVisitorFsm(CompilationConfig.ASM_API_VERSION, transformedClass), true);
originalClass.accept(new ValueHolderReplacementVisitor(mergeGenerator, true));
if (!AsmUtil.isClassOk(logger, classNames.dot, transformedClass)) {
throw new IllegalStateException(String.format("Problem found after transforming %s", classNames.dot));
}
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
transformedClass.accept(writer);
byte[] outputClass = writer.toByteArray();
queryClassLoader.injectByteCode(classNames.dot, outputClass);
Class<?> transformedClazz = queryClassLoader.findClass(classNames.dot);
transformedClazz.getMethod("doSomething").invoke(null);
}
}
use of org.objectweb.asm.tree.ClassNode in project drill by apache.
the class AsmUtil method classFromBytes.
/**
* Create a ClassNode from bytecode.
*
* @param classBytes the bytecode
* @param asmReaderFlags flags for ASM; see {@link org.objectweb.asm.ClassReader#accept(org.objectweb.asm.ClassVisitor, int)}
* @return the ClassNode
*/
public static ClassNode classFromBytes(final byte[] classBytes, final int asmReaderFlags) {
final ClassNode classNode = new ClassNode(CompilationConfig.ASM_API_VERSION);
final ClassReader classReader = new ClassReader(classBytes);
classReader.accept(classNode, asmReaderFlags);
return classNode;
}
use of org.objectweb.asm.tree.ClassNode in project drill by apache.
the class ClassTransformer method getImplementationClass.
public Class<?> getImplementationClass(final QueryClassLoader classLoader, final TemplateClassDefinition<?> templateDefinition, final String entireClass, final String materializedClassName) throws ClassTransformationException {
// unfortunately, this hasn't been set up at construction time, so we have to do it here
final ScalarReplacementOption scalarReplacementOption = ScalarReplacementOption.fromString(optionManager.getOption(ExecConstants.SCALAR_REPLACEMENT_VALIDATOR));
try {
final long t1 = System.nanoTime();
final ClassSet set = new ClassSet(null, templateDefinition.getTemplateClassName(), materializedClassName);
final byte[][] implementationClasses = classLoader.getClassByteCode(set.generated, entireClass);
long totalBytecodeSize = 0;
Map<String, Pair<byte[], ClassNode>> classesToMerge = Maps.newHashMap();
for (byte[] clazz : implementationClasses) {
totalBytecodeSize += clazz.length;
final ClassNode node = AsmUtil.classFromBytes(clazz, ClassReader.EXPAND_FRAMES);
if (!AsmUtil.isClassOk(logger, "implementationClasses", node)) {
throw new IllegalStateException("Problem found with implementationClasses");
}
classesToMerge.put(node.name, Pair.of(clazz, node));
}
final LinkedList<ClassSet> names = Lists.newLinkedList();
final Set<ClassSet> namesCompleted = Sets.newHashSet();
names.add(set);
while (!names.isEmpty()) {
final ClassSet nextSet = names.removeFirst();
if (namesCompleted.contains(nextSet)) {
continue;
}
final ClassNames nextPrecompiled = nextSet.precompiled;
final byte[] precompiledBytes = byteCodeLoader.getClassByteCodeFromPath(nextPrecompiled.clazz);
final ClassNames nextGenerated = nextSet.generated;
// keeps only classes that have not be merged
Pair<byte[], ClassNode> classNodePair = classesToMerge.remove(nextGenerated.slash);
final ClassNode generatedNode;
if (classNodePair != null) {
generatedNode = classNodePair.getValue();
} else {
generatedNode = null;
}
/*
* TODO
* We're having a problem with some cases of scalar replacement, but we want to get
* the code in so it doesn't rot anymore.
*
* Here, we use the specified replacement option. The loop will allow us to retry if
* we're using TRY.
*/
MergedClassResult result = null;
boolean scalarReplace = scalarReplacementOption != ScalarReplacementOption.OFF && entireClass.length() < MAX_SCALAR_REPLACE_CODE_SIZE;
while (true) {
try {
result = MergeAdapter.getMergedClass(nextSet, precompiledBytes, generatedNode, scalarReplace);
break;
} catch (RuntimeException e) {
// if we had a problem without using scalar replacement, then rethrow
if (!scalarReplace) {
throw e;
}
// if we did try to use scalar replacement, decide if we need to retry or not
if (scalarReplacementOption == ScalarReplacementOption.ON) {
// option is forced on, so this is a hard error
throw e;
}
/*
* We tried to use scalar replacement, with the option to fall back to not using it.
* Log this failure before trying again without scalar replacement.
*/
logger.info("scalar replacement failure (retrying)\n", e);
scalarReplace = false;
}
}
for (String s : result.innerClasses) {
s = s.replace(DrillFileUtils.SEPARATOR_CHAR, '.');
names.add(nextSet.getChild(s));
}
classLoader.injectByteCode(nextGenerated.dot, result.bytes);
namesCompleted.add(nextSet);
}
// adds byte code of the classes that have not been merged to make them accessible for outer class
for (Map.Entry<String, Pair<byte[], ClassNode>> clazz : classesToMerge.entrySet()) {
classLoader.injectByteCode(clazz.getKey().replace(DrillFileUtils.SEPARATOR_CHAR, '.'), clazz.getValue().getKey());
}
Class<?> c = classLoader.findClass(set.generated.dot);
if (templateDefinition.getExternalInterface().isAssignableFrom(c)) {
logger.debug("Compiled and merged {}: bytecode size = {}, time = {} ms.", c.getSimpleName(), DrillStringUtils.readable(totalBytecodeSize), (System.nanoTime() - t1 + 500_000) / 1_000_000);
return c;
}
throw new ClassTransformationException("The requested class did not implement the expected interface.");
} catch (CompileException | IOException | ClassNotFoundException e) {
throw new ClassTransformationException(String.format("Failure generating transformation classes for value: \n %s", entireClass), e);
}
}
Aggregations