문제

java.io.invalidclassexception을 얻을 때 원하는 직렬 버전과 직렬 버전을 제공합니다. 잘못된 SerialversionUid를 사용하여 수십 개의 항아리를 알 수있는 쉬운 방법이 있습니까?

업데이트: 우리의 의도는 모든 것을 동시에 업데이트하는 것이지만 빌드 및 배포 프로세스에서 문제를 디버깅하려고합니다.

도움이 되었습니까?

해결책

항아리의 각 클래스에 대해 Sun JDK의 Serialver 도구를 사용하십시오.

다른 팁

이러한 종류의 문제를 처리하는 가장 좋은 방법은 서버 및 클라이언트 측에서 항아리를 동시에 업데이트하는 것입니다. 이렇게하면 양쪽에 동일한 버전의 클래스가 보장되며 직렬화 / 사제화 할 때 문제가 없습니다. 이 문제가 발생할 때마다 일련의 UID 추적은 아무것도 해결하지 못할 것이며, 상당한 시간과 자원 만 낭비 할 것입니다. 시간을 보내고 적절한 배포 / 포장 전략을 구현하는 것이 훨씬 낫습니다.

실제로 다른 선택이없는 경우 각 항아리에서 클래스를로드하는 도구 (UrlClassLoader 사용)를 작성한 다음 사용할 수 있습니다. java.io.ObjectStreamClass.getSerialVersionUID() 필요한 정보를 얻으려면.

다양한 JVM/컨테이너/클래스 로더 조합은 BootClassPath에서 Application/WebApp ClassPath에서 어떤 클래스를로드 해야하는지에 대한 의견이 다릅니다.

이는 Serialver가 항상 BootClassPath에서 항상로드되므로 다른 동작을 시뮬레이션하려면 아래와 같이 -j -xbootclasspath를 사용해야한다는 사실에 의해 복잡합니다.

f=/System/Library/Frameworks/JavaVM.framework/Versions/1.5/Classes/
serialver -J-Xbootclasspath:.:$f/dt.jar:$f/classes.jar:$f/ui.jar javax.xml.namespace.QName

또 다른 방법은 Javap을 사용하는 것입니다.

javap -verbose -bootclasspath . javax.xml.namespace.QName | sed -n -e '/static.*serialVersionUID/{N;p;}'

나는 답을 바탕으로 이것을 수행 할 수있는 유틸리티를 생각해 냈습니다. 여기 내 수업이 있습니다.

package jar;

import java.io.File;
import java.io.IOException;
import java.io.ObjectStreamClass;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;


/**
 * Searches all the jars in a given directory for a class with the given UID.
 * Additional directories can be specified to support with loading the jars.  
 * For example, you might want to load the lib dir from your app server to get
 * the Servlet API, etc.  
 */
public class JarUidSearch
{
    public static void main(String args[])
            throws IOException, ClassNotFoundException
    {
        if( args.length < 2)
        {
            System.err.println("Usage: <UID to search for> <directory with jars to search> [additional directories with jars]");
            System.exit(-1);
        }

        long targetUID = Long.parseLong(args[0]);

        ArrayList<URL> urls = new ArrayList<URL>();

        File libDir = new File(args[1]);

        for (int i = 1; i < args.length; i++)
        {
            gatherJars(urls, new File(args[i]));
        }

        File[] files = libDir.listFiles();

        for (File file : files)
        {
            try
            {
                checkJar(targetUID, urls, file);
            }
            catch(Throwable t)
            {
                System.err.println("checkJar for " + file + " threw: " + t);
                t.printStackTrace();
            }   
        }
    }

    /**
     * 
     * @param urls
     * @param libDir
     * @throws MalformedURLException
     */
    public static void gatherJars(ArrayList<URL> urls, File libDir)
            throws MalformedURLException
    {
        File[] files = libDir.listFiles();

        for (File file : files)
        {
            urls.add(file.toURL());
        }
    }

    /**
     * 
     * @param urls
     * @param file
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public static void checkJar(long targetUID, ArrayList<URL> urls, File file)
            throws IOException, ClassNotFoundException
    {
        System.out.println("Checking: " + file);
        JarFile jarFile = new JarFile(file);
        Enumeration allEntries = jarFile.entries();
        while (allEntries.hasMoreElements())
        {
            JarEntry entry = (JarEntry) allEntries.nextElement();
            String name = entry.getName();

            if (!name.endsWith(".class"))
            {
                // System.out.println("Skipping: " + name);
                continue;
            }

            try
            {
                URLClassLoader loader = URLClassLoader.newInstance((URL[]) urls.toArray(new URL[0]));
                String className = name.substring(0,
                    name.length() - ".class".length()).replaceAll("/", ".");
                Class<?> clazz = loader.loadClass(className);
                ObjectStreamClass lookup = ObjectStreamClass.lookup(clazz);

                if (lookup != null)
                {
                    long uid = lookup.getSerialVersionUID();

                    if (targetUID == uid)
                    {
                        System.out.println(file + " has class: " + clazz);
                    }
                }
            }
            catch (Throwable e)
            {
                System.err.println("entry " + name + " caused Exception: " + e);
            }
        }
    }
}

서투르지 만 작동합니다

리버스 엔지니어링 도구를 사용합니다
1) 항아리를 압축 해제하십시오
2) 클래스 파일 트리에서 jad를 실행합니다.
3)이 새로운 소스 트리에서 GREP 또는 기타 찾기 도구를 실행하여 직렬 버전 UID를 찾으십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top