Package er.profiling.classloader

Source Code of er.profiling.classloader.WeavingClassLoader

package er.profiling.classloader;

import java.lang.instrument.ClassFileTransformer;
import java.lang.reflect.Constructor;
import java.net.URL;
import java.net.URLClassLoader;

import sun.misc.Resource;
import sun.misc.URLClassPath;

/**
* The WeavingClassLoader is a custom URLClassLoader that implements the
* same functionality as the -javaagent transformation feature, passing all
* classes through the ClassTransformer prior to definition.
*
* When this classloader is enabled as a "root loader" and not a conventional hierarchical
* classloader it is important to use caution as it may not work as expected in some cases.
*
* @author q
*
*/
public class WeavingClassLoader extends URLClassLoader {
  public static final String ROOT_LOADER_KEY = "gluonj.WeavingClassLoader.isRootLoader";
  public static final String GLUE_NAME_KEY = "gluonj.GlueName";
  private String glueName;
  private ClassFileTransformer transformer;
 
  {
    glueName = System.getProperty(GLUE_NAME_KEY);
   
    if (glueName == null) {
      System.err.println("GlueName is not defined. Transforming is disabled");
    }
  }

  public WeavingClassLoader(URL[] urls, ClassLoader parent) {
    super(urls, parent);
    if (glueName != null) {
      try {
        @SuppressWarnings("unchecked")
        Class<ClassFileTransformer> clazz = (Class<ClassFileTransformer>) findClass(ClassTransformer.class.getName());
        Constructor<ClassFileTransformer> c = clazz.getConstructor(new Class<?>[] { String.class });
        transformer = c.newInstance(glueName);
      } catch (Exception e) {
        System.err.println("ClassTransformer could not be initialized. Transforming is disabled");
        e.printStackTrace(System.err);
      }
    }
  }

  @Override
  protected synchronized Class<?> loadClass(String name, boolean resolve)
      throws ClassNotFoundException {
    Class<?> clazz = findLoadedClass(name);
    if (clazz != null)
      return clazz;

    if (isNonTransformable(name)) {
      return super.loadClass(name, resolve);
    }

    if (isRootLoader()) {
      try {
        Class<?> c = findClass(name);
        if (resolve) {
          resolveClass(c);
        }

        return c;
      } catch (ClassNotFoundException e) {
      }
    }
    return super.loadClass(name, resolve);
  }

  @Override
  protected Class<?> findClass(String name) throws ClassNotFoundException {
    Class<?> clazz = findLoadedClass(name);
    if (clazz != null)
      return clazz;

    if (isNonTransformable(name)) {
      return super.findClass(name);
    }

    String path = name.replace('.', '/').concat(".class");
    Resource res = new URLClassPath(getURLs()).getResource(path, false);
    if (res != null) {
      try {
        byte[] b = res.getBytes();
        byte[] transformed = transformer.transform(this, name, null,
            null, b);
        if (transformed == null)
          transformed = b;
        return defineClass(name, transformed, 0, transformed.length);
      } catch (Exception e) {
        return super.findClass(name);
      }
    }
    return super.findClass(name);
  }

  /**
   * Determines if a class can be transformed based on the name. In most cases
   * as class is non transformable because it is part of the JRE and loaded by
   * bootstrap classloader.
   *
   * @param className
   * @return whether the class is transformable.
   */
  protected boolean isNonTransformable(String className) {
    return transformer == null
        || className.startsWith("java.")
        || className.startsWith("javax.")
        || (className.startsWith("com.sun.") && !className
            .startsWith("com.sun.script."))
        || className.startsWith("sun.")
        || className.startsWith("sunw.")
        || className.startsWith("javassist.")
        || className.startsWith("org.xml.sax.")
        || className.equals(glueName);
  }
 
  protected boolean isRootLoader() {
    return Boolean.parseBoolean(System.getProperty(ROOT_LOADER_KEY, "false"));
  }

}
TOP

Related Classes of er.profiling.classloader.WeavingClassLoader

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.