ClassFormatError при вызове defineClass с чтением байтов с использованием метода чтения JarInputStream - PullRequest
1 голос
/ 03 марта 2012

Я использую следующий метод для чтения байтов из записей jar (содержащих только файлы классов). Внутри банки нет файла с банкой.

private List<byte[]> readFromJarFile(File cp) 
{
    List<byte[]> cbytes = new ArrayList<byte[]>();
    try 
    {
        java.util.jar.JarInputStream jin = new java.util.jar.JarInputStream(new java.io.FileInputStream(cp));
        java.util.jar.JarEntry je = jin.getNextJarEntry();
        while (je != null)
        {
            if (!je.isDirectory() && je.toString().endsWith(".class")) 
            {
                //assume class file size < Integer.MAX_VALUE
                System.out.printf("readFromJarFile: jar entry name %s ...%n",je.toString());
                byte[] cbyte = new byte[(int) je.getSize()];
                jin.read(cbyte,0,(int) je.getSize());
                cbytes.add(cbyte);
            }
            je = jin.getNextJarEntry();
        }
    }
    catch (java.io.IOException ie)
    {
        ie.printStackTrace();
    }

    return cbytes;
}

Теперь, когда я вызываю defineClass с байтовым массивом, возвращенным из вышеуказанного метода, выдается следующее исключение.

java.lang.ClassFormatError: Unknown constant tag 0 in class file <Unknown>
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
at java.lang.ClassLoader.defineClass(ClassLoader.java:465)
at san.tool.JPAEntityProcessor$JPAClassLoader.loadClass(JPAEntityProcessor.java:34)
at san.tool.JPAEntityProcessor.processJPAEntities(JPAEntityProcessor.java:49)
at san.tool.JPAEntityProcessorTest.testWithJarFile(JPAEntityProcessorTest.java:40)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at 

Я искал этот сайт и все другие форумы в Интернете, но не смог найти ответ. Я с нетерпением жду некоторых идей от участников здесь.

Спасибо и всего наилучшего Santanu

Ответы [ 2 ]

4 голосов
/ 03 марта 2012
jin.read(cbyte,0,(int) je.getSize());

Не гарантируется, что метод read будет считывать je.getSize() байтов в буфер. Вместо этого он возвращает количество прочитанных байтов. Вам нужно заключить попытки чтения в цикл и читать до заполнения буфера.

Примерно так:

int len = (int) je.getSize();
int offset = 0;
int read;
while ((read = jin.read(cbyte, offset, len - offset)) > 0) {
    offset += read;
}

UPD Через год я понял, что мой оригинальный пример застрянет после прочтения всего потока. И позже «исправленная» версия фактически не войдет в цикл. Итак, вот короткая, правильная и проверенная версия.

0 голосов
/ 27 июня 2013

У меня была такая же проблема, и на самом деле правильный способ сделать это:

int read = 0;
int len = (int) je.getSize();
int offset = 0;
do {
    read = jin.read(cbyte, offset, len - offset);
    offset += read;
} while (read > 0);

это я протестировал и работает.Обратите внимание, что в ответе выше он никогда не войдет в цикл, потому что read инициализируется нулем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...