JDK-4187785 : ClassLoader.defineClass throws NoClassDefFoundError on incorrect class name
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang
  • Affected Version: 1.2.0
  • Priority: P4
  • Status: Closed
  • Resolution: Not an Issue
  • OS: solaris_2.5
  • CPU: sparc
  • Submitted: 1998-11-06
  • Updated: 2001-08-02
  • Resolved: 2001-08-02
Description

Name: mgC56079			Date: 11/06/98


ClassLoader.defineClass(String name, byte[] b, int off, int len) 
throws NoClassDefFoundError if name does not match the name derived from 
the class data array. 
According to javadoc, the call should result in a ClassFormatError:

    /**
     * Converts an array of bytes into an instance of class <code>Class</code>.
     * Before the Class can be used it must be resolved.
     * <p>
     * This method assigns a default <code>ProtectionDomain</code> to 
     * the newly defined class. The <code>ProtectionDomain</code> 
     * contains the set of permissions granted when
     * a call to <code>Policy.getPolicy().getPermissions()</code> is made with
     * a Codesource of <code>null,null</code>. The default domain is 
     * created on the first invocation of <code>defineClass</code>, and
     * re-used on subsequent calls.
     * <p>
     * To assign a specific <code>ProtectionDomain</code> to the class,
     * use the <code>defineClass</code> method that takes a 
     * <code>ProtectionDomain</code> as one of its arguments.
     *
     * @param	   name the expected name of the class, or <code>null</code>
     *                  if not known, using '.' and not '/' as the separator
     *                  and without a trailing ".class" suffix.
     * @param      b    the bytes that make up the class data. The bytes in 
     *             positions <code>off</code> through <code>off+len-1</code> 
     *             should have the format of a valid class file as defined 
     *             by the 
     *             <a href="http://java.sun.com/docs/books/vmspec/">Java 
     *             Virtual Machine Specification</a>.
     * @param      off  the start offset of the class data
     * @param      len  the length of the class data
     * @return     the <code>Class</code> object that was created from the
     *             specified class data
     * @exception  ClassFormatError if the data did not contain a valid class
     * @exception  IndexOutOfBoundsException if either <code>off</code> or 
     *             <code>len</code> is negative, or if 
     *             <code>off+len</code> is greater than <code>b.length</code>.
     * @see        ClassLoader#loadClass(java.lang.String, boolean)
     * @see        ClassLoader#resolveClass(java.lang.Class)
     * @see        java.security.ProtectionDomain
     * @see        java.security.Policy
     * @see        java.security.CodeSource
     * @see        java.security.SecureClassLoader
     * @since      JDK1.1
     */
    protected final Class defineClass(String name, byte[] b, int off, int len)
	throws ClassFormatError

==== here is the test demonstrating the bug (CLoader.java) ====
import java.io.FileInputStream;
public class CLoader  {

    public static void main(String[] s) {
      MyClassLoader loader = new MyClassLoader();
      byte[] source=new byte[10000];
      int len;
      try {
          FileInputStream f=new FileInputStream("CLoader.class");  
          len=f.read(source,0,source.length);
      }
      catch (Exception e) {
          e.printStackTrace();
          return;
      }
      try {
        loader.myDefineClass("incorrect.class.name",source,0,len);
        System.out.println("failed: unexpected success");
      }
      catch (ClassFormatError e) {
          System.out.println("passed");
      }
      catch (Throwable t) {
          System.out.println("failed");
          t.printStackTrace();
      }
    }

}

class MyClassLoader extends ClassLoader {

    public Class myDefineClass(String name, byte[] b, int off, int len) {
        return defineClass(name, b, off, len);
    }

}
==== sample run (jdk1.2fcsQ) ====
% java CLoader
failed
java.lang.NoClassDefFoundError: incorrect/class/name (wrong name: CLoader)
	at java.lang.ClassLoader.defineClass0(Native Method)
	at java.lang.ClassLoader.defineClass(Compiled Code)
	at MyClassLoader.myDefineClass(Compiled Code)
	at CLoader.main(Compiled Code)

======================================================================

Comments
PUBLIC COMMENTS The VM spec clearly defines the correct behavior in JVMS 5.3.5 (item 2, 3rd bullet)
10-06-2004

EVALUATION This is not a bug. The ClassLoader javadoc is in fact completely silent on this matter. JVMS 2nd edition, section 5.3.5, specifies what the VM (as distinct from ClassLoader) does in such a situation. In general, ClassLoader forwards these errors to the user. This what is done in this case as well. Thus, both the VM spec and compatibility dictate that this is the desired behavior. gilad.bracha@eng 2001-02-21
21-02-2001