content: /*
   * Copyright (C) 2016 david.wei (lighters)
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *       http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package com.lighters.asm;
  
  /***
   * ASM examples: examples showing how ASM can be used
   * Copyright (c) 2000-2011 INRIA, France Telecom
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   * 1. Redistributions of source code must retain the above copyright
   * notice, this list of conditions and the following disclaimer.
   * 2. Redistributions in binary form must reproduce the above copyright
   * notice, this list of conditions and the following disclaimer in the
   * documentation and/or other materials provided with the distribution.
   * 3. Neither the name of the copyright holders nor the names of its
   * contributors may be used to endorse or promote products derived from
   * this software without specific prior written permission.
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
   * THE POSSIBILITY OF SUCH DAMAGE.
   */
  
  import java.io.FileOutputStream;
  import java.io.PrintStream;
  import org.objectweb.asm.ClassWriter;
  import org.objectweb.asm.MethodVisitor;
  import org.objectweb.asm.Opcodes;
  import org.objectweb.asm.Type;
  import org.objectweb.asm.commons.GeneratorAdapter;
  import org.objectweb.asm.commons.Method;
  
  /**
   * @author Eric Bruneton
   */
  public class HelloWorld extends ClassLoader implements Opcodes {
  
      public static void main(final String args[]) throws Exception {
          // Generates the bytecode corresponding to the following Java class:
          //
          // public class Example {
          // public static void main (String[] args) {
          // System.out.println("Hello world!");
          // }
          // }
  
          // creates a ClassWriter for the Example public class,
          // which inherits from Object
          ClassWriter cw = new ClassWriter(0);
          cw.visit(V1_1, ACC_PUBLIC, "Example", null, "java/lang/Object", null);
  
          // creates a MethodWriter for the (implicit) constructor
          MethodVisitor mw = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
          // pushes the 'this' variable
          mw.visitVarInsn(ALOAD, 0);
          // invokes the super class constructor
          mw.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
          mw.visitInsn(RETURN);
          // this code uses a maximum of one stack element and one local variable
          mw.visitMaxs(1, 1);
          mw.visitEnd();
  
          // creates a MethodWriter for the 'main' method
          mw = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);
          // pushes the 'out' field (of type PrintStream) of the System class
          mw.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
          // pushes the "Hello World!" String constant
          mw.visitLdcInsn("Hello world!");
          // invokes the 'println' method (defined in the PrintStream class)
          mw.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
          mw.visitInsn(RETURN);
          // this code uses a maximum of two stack elements and two local
          // variables
          mw.visitMaxs(2, 2);
          mw.visitEnd();
  
          // gets the bytecode of the Example class, and loads it dynamically
          byte[] code = cw.toByteArray();
  
          FileOutputStream fos = new FileOutputStream("Example.class");
          fos.write(code);
          fos.close();
  
          HelloWorld loader = new HelloWorld();
          Class<?> exampleClass = loader.defineClass("Example", code, 0, code.length);
  
          // uses the dynamically generated class to print 'Helloworld'
          exampleClass.getMethods()[0].invoke(null, new Object[] { null });
  
          // ------------------------------------------------------------------------
          // Same example with a GeneratorAdapter (more convenient but slower)
          // ------------------------------------------------------------------------
  
          cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
          cw.visit(V1_1, ACC_PUBLIC, "Example", null, "java/lang/Object", null);
  
          // creates a GeneratorAdapter for the (implicit) constructor
          Method m = Method.getMethod("void <init> ()");
          GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC, m, null, null, cw);
          mg.loadThis();
          mg.invokeConstructor(Type.getType(Object.class), m);
          mg.returnValue();
          mg.endMethod();
  
          // creates a GeneratorAdapter for the 'main' method
          m = Method.getMethod("void main (String[])");
          mg = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC, m, null, null, cw);
          mg.getStatic(Type.getType(System.class), "out", Type.getType(PrintStream.class));
          mg.push("Hello world!");
          mg.invokeVirtual(Type.getType(PrintStream.class), Method.getMethod("void println (String)"));
          mg.returnValue();
          mg.endMethod();
  
          cw.visitEnd();
  
          code = cw.toByteArray();
          loader = new HelloWorld();
          exampleClass = loader.defineClass("Example", code, 0, code.length);
  
          // uses the dynamically generated class to print 'Helloworld'
          exampleClass.getMethods()[0].invoke(null, new Object[] { null });
      }
  }
  
  
  