This discussion is archived
12 Replies Latest reply: Feb 19, 2010 3:26 PM by EJP RSS

Class loader - ClassFormatError

843798 Newbie
Currently Being Moderated
Hey guys,
I have a problem with my loading a class file, I get this error:

Exception in thread "AWT-EventQueue-0" java.lang.ClassFormatError: Code segment has wrong length in class file j2MeDataChunkGenerator_Plugin/DataChunkGenerator.class

I know I compiled it right, since other classes does load, I didn't try to manipulate the byte code or any thing like this, could anything code related might generate this kind of exception??

in the beginning I thought this was an error with my class loading process, but once I recreated an empty duplicate of the problem, it works fine, and all the classes are been loaded correctly.

Any help or idea would be greatly appreciated, I've been at it for 4 evenings ;..(
Thanks in advance,
Adam.
  • 1. Re: Class loader - ClassFormatError
    843798 Newbie
    Currently Being Moderated
    I should have put this earlier:
    the class loading method:
         public static class PluginClassLoader extends ClassLoader {
              
              // public PluginClassLoader() {
              // super(new URL[] {});
              // }
              
              private ArrayList<JarFile> jars = new ArrayList<JarFile>();
              public synchronized void add(JarFile jar) throws MalformedURLException {
                   jars.add(jar);
              }
              
              public Class<?> loadClass(String className) throws ClassNotFoundException {
                   try {
                        try {
                             System.out.println("Looking in super.loadClass(className=" + className + ")");
                             Class<?> _class=super.loadClass(className);
                             System.out.println("Class was found: "+className);
                             return _class;
                             // return checkIfClassWasLoaded(className, false);
                        } catch (ClassNotFoundException e1) {
                             System.out.println("Class was not found: "+className);
                             System.out.println("Looking in the Jar files for className=" + className);
                             for (int i = 0; i < jars.size(); i++) {
                                  JarFile jar = jars.get(i);
                                  Enumeration<JarEntry> enumeration = jar.entries();
                                  while (enumeration.hasMoreElements()) {
                                       java.util.jar.JarEntry file = (JarEntry) enumeration.nextElement();
                                       if (file.getName().equals(className.replace(".", "/") + ".class")) {
                                            System.out.println("A match to " + className + " was found in: \n" + jar.getName().replace("\\", "/") + "!/" + file.getName()+"\n");
                                            InputStream is = jar.getInputStream(file);
                                            byte[] bytes;
                                            int length = is.available();
                                            bytes = new byte[length];
                                            is.read(bytes);
                                            return defineClass(className, bytes, 0, bytes.length);
                                       }
                                  }
                             }
                        }
                   } catch (IOException e) {
                        System.out.println("Unable to locate class file: " + className);
                        e.printStackTrace();
                   }
                   
                   throw new ClassNotFoundException(className);
              }
              private Class<?> checkIfClassWasLoaded(String className, boolean pResolve) throws ClassNotFoundException {
                   System.out.println("checkIfClassWasLoaded(" + className + ", " + pResolve + ")");
                   Class<?> lClass = findLoadedClass(className);
                   if (lClass == null) {
                        try {
                             ClassLoader lParent = getParent();
                             if (lParent == null) {
                                  lClass = getSystemClassLoader().loadClass(className);
                             } else {
                                  lClass = lParent.loadClass(className);
                             }
                        } catch (ClassNotFoundException cnfe) {
                             lClass = findSystemClass(className);
                        }
                   }
                   try {
                        if (pResolve) {
                             System.out.println("resolve class: " + lClass);
                             resolveClass(lClass);
                        }
                   } catch (Error e) {
                        e.printStackTrace();
                        throw e;
                   }
                   return lClass;
              }
              
              /**
               * checks if this plugin .jar file was loaded already into this class
               * loader jar list.
               * 
               * @param file
               *            - the file of the plugin jar
               * @return
               * @throws IOException
               */
              public JarFile contains(String jarPath) {
                   for (JarFile file : jars)
                        if (file.getName().equalsIgnoreCase(jarPath))
                             return file;
                   return null;
              }
         }
  • 2. Re: Class loader - ClassFormatError
    791266 Explorer
    Currently Being Moderated
    Adam-Z. wrote:
    Hey guys,
    I have a problem with my loading a class file, I get this error:

    Exception in thread "AWT-EventQueue-0" java.lang.ClassFormatError: Code segment has wrong length in class file j2MeDataChunkGenerator_Plugin/DataChunkGenerator.class
    So, is the DataChunkGenerator a valid class?
  • 3. Re: Class loader - ClassFormatError
    843798 Newbie
    Currently Being Moderated
    So, is the DataChunkGenerator a valid class?
    As far as my actions to create this class file concern, yes this is a valid class file, and the file exists in the jar, I even get the byte code of the correct byte size, I can see size of the .class file in the jar via WinRar... and when I put the DataChunkGenerator in the build path of the main application, it does load it without a ClassFormatError.
  • 4. Re: Class loader - ClassFormatError
    843798 Newbie
    Currently Being Moderated
    Oh, I get it now, you were cynical... well yes, Obviously something is wrong, what I mean is, does any one know, if something systematic in the scenario I described, might causes the segment Format error?

    Sorry for not making that clear earlier...

    perhaps Jar-ing the package without a few java files that the object needs? Na, this should result in a ClassNotFoundException not a segment format error.

    I wonder what obvious element did I miss that can cause the FormatException, when I'm positive I did not manipulate the class byte code yet a FormatException occur... and when I compile and run the project in eclipse with the package in the application main build path it works fine.

    Thanks in advance,
    Adam.
  • 5. Re: Class loader - ClassFormatError
    798701 Newbie
    Currently Being Moderated
    Probably you are reading only a portion of the class file.
     [snip]
                        InputStream is = jar.getInputStream(file);
                        byte[] bytes;
                        int length = is.available();
                        bytes = new byte[length];
                        is.read(bytes);
                        return defineClass(className, bytes, 0, bytes.length);
    [snip]
    The available() method doesn't return the size of the class file, only the number of bytes that the input stream has available in a buffer and can be read without blocking. Also, the read method doesn't necessarily fill the entire byte array with data. It returns the number of bytes that has been read. Several calls to read() may be required to read the class file.
  • 6. Re: Class loader - ClassFormatError
    791266 Explorer
    Currently Being Moderated
    Adam-Z. wrote:
    Oh, I get it now, you were cynical...
    No, I wasn't.

    I think I found your problem, now when I knew what to look for. This isn't correct:
    InputStream is = jar.getInputStream(file);
                             byte[] bytes;
                             int length = is.available();
                             bytes = new byte[length];
                             is.read(bytes);
    Read returns how many bytes that you received during the read. You should read in a loop, and you shouldn't use available();

    Edit: Too slow :(
  • 7. Re: Class loader - ClassFormatError
    791266 Explorer
    Currently Being Moderated
    This is how I read zip-entries (in an Android device)
    out = new BufferedOutputStream(new FileOutputStream(destination), 1024);
    in = new BufferedInputStream(zip.getInputStream(entry), 2048);
    byte[] buffer = new byte[1024];
    int length = 0;
    while ((length = in.read(buffer)) != -1) {
         out.write(buffer, 0, length);
    }
    out.flush();
    You should do something similar, but you can write to a ByteArrayOutputStream instead, so that you can get all your bytes when you are done reading.

    Kaj
  • 8. Re: Class loader - ClassFormatError
    843798 Newbie
    Currently Being Moderated
    You should do something similar, but you can write to a ByteArrayOutputStream instead, so that you can get all your bytes when you are done reading.
    I'll check this now, just so you would know i did compare the sizes of both the class file and the byte array size matched, regardless if it is a good idea or not.

    Adam.
  • 9. Re: Class loader - ClassFormatError
    791266 Explorer
    Currently Being Moderated
    Adam-Z. wrote:
    You should do something similar, but you can write to a ByteArrayOutputStream instead, so that you can get all your bytes when you are done reading.
    I'll check this now, just so you would know i did compare the sizes of both the class file and the byte array size matched, regardless if it is a good idea or not.

    Adam.
    That could happen if available gave the correct size, but read didn't read all bytes. You would in that case have zeroes at the end.
  • 10. Re: Class loader - ClassFormatError
    843798 Newbie
    Currently Being Moderated
    wow guys... this is so exciting, it works great, thank you all, really.

    why does this error occur really, why doesn't the read() reads all the size of the byte array?
  • 11. Re: Class loader - ClassFormatError
    791266 Explorer
    Currently Being Moderated
    Adam-Z. wrote:
    wow guys... this is so exciting, it works great, thank you all, really.

    why does this error occur really, why doesn't the read() reads all the size of the byte array?
    It's implementation (and could also be platform) specific. It probably reads one logical block or something like that. The only important thing is that the javadoc for read() states that this is how it works.

    You should always read the javadoc before you use something.
  • 12. Re: Class loader - ClassFormatError
    EJP Guru
    Currently Being Moderated
    why doesn't the read() reads all the size of the byte array?
    Where does it say that it will? and why did you assume something that isn't documented anywhere?