Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/353.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 查找jar中具有给定serialVersionUID的类_Java_Serialversionuid - Fatal编程技术网

Java 查找jar中具有给定serialVersionUID的类

Java 查找jar中具有给定serialVersionUID的类,java,serialversionuid,Java,Serialversionuid,当我得到一个java.io.InvalidClassException时,它会给我它想要的SerialVersionId和它得到的SerialVersionId。有没有一种简单的方法来判断我的几十个罐子中哪些使用了错误的serialVersionUID 更新:我应该提到,我们的目的是同时更新所有内容,但我正在尝试调试构建和部署过程中的一个问题。处理此类问题的最佳方法是同时更新服务器端和客户端上的JAR。这将保证两侧的类版本相同,并且在序列化/反序列化时不会出现问题。每次出现此问题时跟踪串行UID

当我得到一个java.io.InvalidClassException时,它会给我它想要的SerialVersionId和它得到的SerialVersionId。有没有一种简单的方法来判断我的几十个罐子中哪些使用了错误的serialVersionUID


更新:我应该提到,我们的目的是同时更新所有内容,但我正在尝试调试构建和部署过程中的一个问题。

处理此类问题的最佳方法是同时更新服务器端和客户端上的JAR。这将保证两侧的类版本相同,并且在序列化/反序列化时不会出现问题。每次出现此问题时跟踪串行UID并不能解决任何问题,只会浪费大量的时间和资源。最好花点时间实施适当的部署/打包策略


如果您真的没有其他选择,您可以编写一个工具,使用URLClassLoader从每个jar加载一个类,然后使用java.io.ObjectStreamClass.getSerialVersionUID获取所需信息。

处理此类问题的最佳方法是同时更新服务器端和客户端上的jar。这将保证两侧的类版本相同,并且在序列化/反序列化时不会出现问题。每次出现此问题时跟踪串行UID并不能解决任何问题,只会浪费大量的时间和资源。最好花点时间实施适当的部署/打包策略

如果您真的没有其他选择,您可以编写一个工具,使用URLClassLoader从每个jar加载一个类,然后使用java.io.ObjectStreamClass.getSerialVersionUID获取所需的信息。

笨拙但有效

我会使用逆向工程工具 1打开罐子的拉链 2在类文件树上运行jad 3在这个新的源代码树上运行grep或任何其他查找工具来查找串行版本的uid。

笨拙但有效

我会使用逆向工程工具 1打开罐子的拉链 2在类文件树上运行jad
3在这个新的源代码树上运行grep或任何其他查找工具来查找串行版本uid。

对jar中的每个类使用sunjdk中的serialver工具

对jar中的每个类使用sunjdk中的serialver工具

请记住,不同的JVM/container/classloader组合对应该从bootclasspath加载哪些类与从应用程序/webapp类路径加载哪些类有不同的看法

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;}'

请记住,不同的JVM/容器/类加载器组合对应该从bootclasspath加载哪些类与从应用程序/webapp类路径加载哪些类有不同的看法

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;}'

基于SO中的一些答案,我提出了一个实用程序来执行此操作。这是我的课

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);
            }
        }
    }
}

基于SO中的一些答案,我提出了一个实用程序来执行此操作。这是我的课

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);
            }
        }
    }
}

我在Linux上使用此命令检查当前目录中的所有JAR:

find . -type f -name "*.jar" -exec sh -c 'javap -verbose -p -constants -cp {} com.myCompany.myClass | grep serialVersionUID' \;

请记住,serialVersionUID可能不会在类中显式声明。在这种情况下,serialVersionUID将在运行时计算,无法使用上面的find命令进行搜索。

我在Linux上使用此命令检查当前目录中的所有JAR:

find . -type f -name "*.jar" -exec sh -c 'javap -verbose -p -constants -cp {} com.myCompany.myClass | grep serialVersionUID' \;

请记住,serialVersionUID可能不会在类中显式声明。在这种情况下,serialVersionUID将在运行时计算,无法使用上面的find命令进行搜索。

JAR不使用serialVersionUID。当然可以。这个类在错误消息中被命名,因此你所要做的就是找到这个类,而这个问题实际上毫无意义。没有什么可以阻止您对JAR文件中的每个类或整个企业使用相同的值,例如1L。不清楚你在问什么。JAR不使用SerialVersionUID。当然可以。这个类在错误消息中被命名,因此你所要做的就是找到这个类,而这个问题实际上毫无意义。没有什么可以阻止您对JAR文件中的每个类或整个企业使用相同的值,例如1L。不清楚你在问什么。