3 Replies Latest reply on Aug 5, 2003 1:14 PM by Jeff Grigg

    'MyClass.class.getPackage()' returns null under javassist

    Jeff Grigg Newbie

      Classes have 'null' package during initialization when created under javassist, but not when preloaded by host program before loading under javassist loader.

      Test program:
      _ _ _

      package javassistNullPackageProblem;

      import java.lang.reflect.Method;

      import javassist.CannotCompileException;
      import javassist.ClassPool;
      import javassist.CtClass;
      import javassist.Loader;
      import javassist.NotFoundException;
      import javassist.Translator;

      public class JavaApplicationEntryPoint
      {
      public static void main(final String[] args) throws Exception
      {
      System.out.println("\n" + "Start of test:");

      final HostClassUnderTest test = new HostClassUnderTest();
      test.doNothingMethod();

      //try {
      call_creatANewObject_though_javassist();
      //} catch (final ExceptionInInitializerError ex) {
      // System.out.println(" direct call without javassist >>>---> ExceptionInInitializerError (probably a NullPointerException)");
      //}

      test.creatANewObject("direct call without javassist");
      call_creatANewObject_though_javassist();

      System.out.println("End of test.");
      }

      private static void call_creatANewObject_though_javassist() throws Exception
      {
      // This translator simply displays the names of classes that are being loaded.
      final Translator translator = new Translator()
      {
      public void start(ClassPool pool)
      {
      }

      public void onWrite(ClassPool pool, String className) throws NotFoundException, CannotCompileException
      {
      final CtClass clazz = pool.get(className);
      System.out.println(" Loading class: " + className);
      }
      };

      // Setup javassist.
      final ClassPool jaClassPool = ClassPool.getDefault(translator);
      final Loader jaLoader = new Loader(jaClassPool);
      Thread.currentThread().setContextClassLoader(jaLoader);

      // Load the following class under javassist.
      final Class clazz = jaLoader.loadClass("javassistNullPackageProblem.HostClassUnderTest");

      // Create an instrumented instance of this class.
      final Object instrumentedTestInstance = clazz.newInstance();

      // Find the 'public void creatANewObject(final String message)' method.
      final Class[] parameterClasses = new Class[] { String.class };
      final Method currentMethod = clazz.getDeclaredMethod("creatANewObject", parameterClasses);

      // Call 'instrumentedTestInstance.creatANewObject("call method through javassist");'
      try
      {
      final Object[] parameterValues = new Object[] { "call method through javassist" };
      currentMethod.invoke(instrumentedTestInstance, parameterValues);
      }
      catch (final java.lang.reflect.InvocationTargetException exceptionWrapper)
      {
      /*NOTREACHED*/
      final Throwable originalException = exceptionWrapper.getTargetException();

      if (originalException != null) {
      if (originalException instanceof Exception) {
      throw (Exception) originalException;
      } else if (originalException instanceof Error) {
      throw (Error) originalException;
      }
      }

      throw exceptionWrapper;
      }
      }
      }
      _ _ _

      package javassistNullPackageProblem;

      import javassistNullPackageProblem.someOtherPackage.ChildClassWithPackageProblem;

      public class HostClassUnderTest
      {
      public void doNothingMethod()
      {
      }

      public void creatANewObject(final String message)
      {
      final Object anonymousInnerClassInstance = new Object()
      {
      final Class clazz = ChildClassWithPackageProblem.class;

      final Package staticInstanceVariableFromClass = ChildClassWithPackageProblem.currentPackage;
      final Package reflectionGetPackageCall = clazz.getPackage();
      final Package reflectionCallFromClassReference = ChildClassWithPackageProblem.class.getPackage();

      {
      if (staticInstanceVariableFromClass == null && reflectionGetPackageCall == null && reflectionCallFromClassReference == null)
      {
      System.out.println(" " + message + " >>>---> 'package' is 'null'");
      }
      else if (staticInstanceVariableFromClass != null || reflectionGetPackageCall != null || reflectionCallFromClassReference != null)
      {
      System.out.println(" " + message + " >>>---> 'package' is defined");
      }
      else
      {
      /*NOTREACHED*/
      System.out.println(" " + message + " >>>---> some mix of 'null' and other in package");
      }
      }
      };

      int i=0; // (Place holder for debugger break point.)
      }
      }
      _ _ _

      package javassistNullPackageProblem.someOtherPackage;

      public class ChildClassWithPackageProblem
      {
      public static final Package currentPackage = ChildClassWithPackageProblem.class.getPackage();

      // Uncomment the following line to receive a java.lang.NullPointerException
      // (...within a java.lang.ExceptionInInitializerError, which is within a java.lang.reflect.InvocationTargetException)
      //private static final String packageName = currentPackage.getName();
      }
      _ _ _

      Results:

      Start of test:

      Loading class: javassistNullPackageProblem.HostClassUnderTest

      Loading class: javassistNullPackageProblem.HostClassUnderTest$1

      Loading class: javassistNullPackageProblem.someOtherPackage.ChildClassWithPackageProblem

      call method through javassist >>>---> 'package' is 'null'

      direct call without javassist >>>---> 'package' is defined

      call method through javassist >>>---> 'package' is defined

      End of test.
      _ _ _

      The interesting thing to note is where it says "'package' is 'null'" -- which means that the class 'javassistNullPackageProblem.someOtherPackage.ChildClassWithPackageProblem' has 'null' for its 'java.lang.Package'.

      Note also, two lines later, where it says "'package' is defined" -- meaning that the same class, created the same way, now has a proper package.
      _ _ _

      This is a simple test program which reproduces the problem, but I'm not sure how to debug it from here.

      Thank you for any assistance you may be able to offer!
      - jeff