use of org.objectweb.asm.commons.GeneratorAdapter in project cdap by caskdata.
the class HttpHandlerGenerator method generateLogger.
/**
* Generates a static Logger field for logging and a static initialization block to initialize the logger.
*/
private void generateLogger(Type classType, ClassWriter classWriter) {
// private static final Logger LOG = LoggerFactory.getLogger(classType);
classWriter.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL, "LOG", Type.getType(Logger.class).getDescriptor(), null, null);
Method init = Methods.getMethod(void.class, "<clinit>");
GeneratorAdapter mg = new GeneratorAdapter(Opcodes.ACC_STATIC, init, null, null, classWriter);
mg.visitLdcInsn(classType);
mg.invokeStatic(Type.getType(LoggerFactory.class), Methods.getMethod(Logger.class, "getLogger", Class.class));
mg.putStatic(classType, "LOG", Type.getType(Logger.class));
mg.returnValue();
mg.endMethod();
}
use of org.objectweb.asm.commons.GeneratorAdapter in project cdap by caskdata.
the class ContainerLauncherGenerator method generateMainClass.
/**
* Generates a class that has a static main method which delegates the call to a static method in the given delegator
* class with method signature {@code public static void launch(String className, String[] args)}
*
* @param className the classname of the generated class
* @param mainDelegator the class to delegate the main call to
* @param output for writing the generated bytes
*/
private static void generateMainClass(String className, Type mainDelegator, JarOutputStream output) throws IOException {
String internalName = className.replace('.', '/');
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
classWriter.visit(Opcodes.V1_7, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, internalName, null, Type.getInternalName(Object.class), null);
// Generate the default constructor, which just call super()
Method constructor = Methods.getMethod(void.class, "<init>");
GeneratorAdapter mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC, constructor, null, null, classWriter);
mg.loadThis();
mg.invokeConstructor(Type.getType(Object.class), constructor);
mg.returnValue();
mg.endMethod();
// Generate the main method
// public static void main(String[] args) throws Exception {
// System.out.println("Launch class .....");
// <MainDelegator>.launch(<className>, args);
// }
Method mainMethod = Methods.getMethod(void.class, "main", String[].class);
mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, mainMethod, null, new Type[] { Type.getType(Exception.class) }, classWriter);
mg.getStatic(Type.getType(System.class), "out", Type.getType(PrintStream.class));
mg.visitLdcInsn("Launch class " + className + " by calling " + mainDelegator.getClassName() + ".launch");
mg.invokeVirtual(Type.getType(PrintStream.class), Methods.getMethod(void.class, "println", String.class));
// The main classname is stored as string literal in the generated class
mg.visitLdcInsn(className);
mg.loadArg(0);
mg.invokeStatic(mainDelegator, Methods.getMethod(void.class, "launch", String.class, String[].class));
mg.returnValue();
mg.endMethod();
classWriter.visitEnd();
output.putNextEntry(new JarEntry(internalName + ".class"));
output.write(classWriter.toByteArray());
}
use of org.objectweb.asm.commons.GeneratorAdapter in project cdap by caskdata.
the class SparkClassRewriter method rewriteExecutorClassLoader.
/**
* Rewrites the ExecutorClassLoader so that it won't use system classloader as parent since CDAP classes
* are not in system classloader.
* Also optionally overrides the getResource, getResources and getResourceAsStream methods if they are not
* defined (for fixing SPARK-11818 for older Spark < 1.6).
*/
private byte[] rewriteExecutorClassLoader(InputStream byteCodeStream) throws IOException {
ClassReader cr = new ClassReader(byteCodeStream);
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
final Type classloaderType = Type.getType(ClassLoader.class);
final Type parentClassLoaderType = Type.getObjectType("org/apache/spark/util/ParentClassLoader");
final Method parentLoaderMethod = new Method("parentLoader", parentClassLoaderType, new Type[0]);
// Map from getResource* methods to the method signature
// (can be null, since only method that has generic has signature)
final Map<Method, String> resourceMethods = new HashMap<>();
Method method = new Method("getResource", Type.getType(URL.class), new Type[] { Type.getType(String.class) });
resourceMethods.put(method, null);
method = new Method("getResources", Type.getType(Enumeration.class), new Type[] { Type.getType(String.class) });
resourceMethods.put(method, Signatures.getMethodSignature(method, new TypeToken<Enumeration<URL>>() {
}, TypeToken.of(String.class)));
method = new Method("getResourceAsStream", Type.getType(InputStream.class), new Type[] { Type.getType(String.class) });
resourceMethods.put(method, null);
cr.accept(new ClassVisitor(Opcodes.ASM5, cw) {
private boolean hasParentLoader;
private boolean rewriteInit;
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
// Only rewrite `<init>` if the ExecutorClassloader extends from ClassLoader
if (classloaderType.getInternalName().equals(superName)) {
rewriteInit = true;
}
super.visit(version, access, name, signature, superName, interfaces);
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
// If the resource method is declared, no need to generate at the end.
Method method = new Method(name, desc);
resourceMethods.remove(method);
hasParentLoader = hasParentLoader || parentLoaderMethod.equals(method);
if (!rewriteInit || !"<init>".equals(name)) {
return mv;
}
return new GeneratorAdapter(Opcodes.ASM5, mv, access, name, desc) {
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
// If there is a call to `super()`, skip that instruction and have the onMethodEnter generate the call
if (opcode == Opcodes.INVOKESPECIAL && Type.getObjectType(owner).equals(classloaderType) && name.equals("<init>") && Type.getArgumentTypes(desc).length == 0 && Type.getReturnType(desc).equals(Type.VOID_TYPE)) {
// Generate `super(null)`. The `this` is already in the stack, so no need to `loadThis()`
push((Type) null);
invokeConstructor(classloaderType, new Method("<init>", Type.VOID_TYPE, new Type[] { classloaderType }));
} else {
super.visitMethodInsn(opcode, owner, name, desc, itf);
}
}
};
}
@Override
public void visitEnd() {
// All implementations are delegating to the parentLoader
if (!hasParentLoader) {
super.visitEnd();
return;
}
for (Map.Entry<Method, String> entry : resourceMethods.entrySet()) {
// Generate the method.
// return parentLoader().getResource*(arg)
Method method = entry.getKey();
MethodVisitor mv = super.visitMethod(Modifier.PUBLIC, method.getName(), method.getDescriptor(), entry.getValue(), null);
GeneratorAdapter generator = new GeneratorAdapter(Modifier.PUBLIC, method, mv);
// call `parentLoader()`
generator.loadThis();
generator.invokeVirtual(SPARK_EXECUTOR_CLASSLOADER_TYPE, parentLoaderMethod);
// Load the argument
generator.loadArg(0);
// Call the method on the parent loader.
generator.invokeVirtual(parentClassLoaderType, method);
generator.returnValue();
generator.endMethod();
}
}
}, ClassReader.EXPAND_FRAMES);
return cw.toByteArray();
}
Aggregations