Jar加载顺序的简介说明

书欣 Java经验 发布时间:2022-09-02 15:31:41 阅读数:11697 1
下文笔者讲述java中jar加载顺序的简介说明,如下所示
 今天遇到奇怪的现象
  一个应用在一台服务器上运行正常,
  另一台服务器上运行异常
  仔细查看日志
    原来就是 java.lang.NoSuchMethodError 
	加载jar异常,导致数据jar异常
 

那么如何处理此类异常

 排查两个系统是否一致
    1.linux版本
	2.jdk版本
	3.tomcat版本
	4.程序版本
	5.系统环境变量是否一致
最后测试发现类的加载顺序不同
   一台机器上加载正确的版本,另一台机器加载了一个错误版本的jar包
   所以才会出现异常

为什么不同机器,加载类不同呢?

类加载入口

/**
     * Load the class with the specified name.  This method searches for
     * classes in the same manner as <code>loadClass(String, boolean)</code>
     * with <code>false</code> as the second argument.
     *
     * @param name The binary name of the class to be loaded
     *
     * @exception ClassNotFoundException if the class was not found
     */
    @Override
    public Class<?> loadClass(String name) throws ClassNotFoundException {
        return loadClass(name, false);
    }
首次class文件从jar包中找到的过程
调用StandardRoot.getResourceInternal寻找class
顺序就是循环allResources(格式:list<List<WebResourceSet>>)

protected final WebResource getResourceInternal(String path,
            boolean useClassLoaderResources) {
        WebResource result = null;
        WebResource virtual = null;
        WebResource mainEmpty = null;
        for (List<WebResourceSet> list : allResources) {
            for (WebResourceSet webResourceSet : list) {
                if (!useClassLoaderResources &&  !webResourceSet.getClassLoaderOnly() ||
                        useClassLoaderResources && !webResourceSet.getStaticOnly()) {
                    result = webResourceSet.getResource(path);
                    if (result.exists()) {
                        return result;
                    }
                    if (virtual == null) {
                        if (result.isVirtual()) {
                            virtual = result;
                        } else if (main.equals(webResourceSet)) {
                            mainEmpty = result;
                        }
                    }
                }
            }
        }
        ...
    }
集合classResources存了WEB-INF/lib目录的Jar资源
在Tomcat启动时调用processWebInfLib()方法初始化。

/**
    protected void processWebInfLib() throws LifecycleException {
        WebResource[] possibleJars = listResources("/WEB-INF/lib", false);

        for (WebResource possibleJar : possibleJars) {
            if (possibleJar.isFile() && possibleJar.getName().endsWith(".jar")) {
                createWebResourceSet(ResourceSetType.CLASSES_JAR,
                        "/WEB-INF/classes", possibleJar.getURL(), "/");
            }
        }
    }
    
最终在DirResourceSet类list(String path)方法
其实调用的是java.io.File类list()方法
list调的是UnixFileSystem的native的list()方法

无法保证结果数组中的名称字符串将以任何特定的顺序出现
尤其不能保证它们按字母顺序出现。

OpenJDK

jdk8对应的OpenJDK源码,UnixFileSystem的list方法,调用的是目录操作函数opendir.
JNIEXPORT jobjectArray JNICALL
Java_java_io_UnixFileSystem_list(JNIEnv *env, jobject this,
                                 jobject file)
{
    DIR *dir = NULL;
    struct dirent64 *ptr;
    struct dirent64 *result;
    int len, maxlen;
    jobjectArray rv, old;

    WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
        dir = opendir(path);
    } END_PLATFORM_STRING(env, path);
    if (dir == NULL) return NULL;

    ptr = malloc(sizeof(struct dirent64) + (PATH_MAX + 1));
    if (ptr == NULL) {
        JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
        closedir(dir);
        return NULL;
    }

    ...
}

Linux操作系统

继续向下查操作系统,opendir返回值定义
struct dirent 
{
   ino_t          d_ino;       /* Inode number */
   off_t          d_off;       /* Not an offset; see below */
   unsigned short d_reclen;    /* Length of this record */
   unsigned char  d_type;      /* Type of file; not supported
                                  by all filesystem types */
   char           d_name[256]; /* Null-terminated filename */
};

对readdir()的连续调用读取文件名的顺序取决于文件系统实现
不太可能以任何方式对文件名进行排序。
命令ll -f与opendir函数readdir顺序相同

文件系统

 CentOS 6使用的是Ext4
文件顺序与目录文件的大小是否超过一个磁盘块和文件系统计算的Hash值有关
由于Java语言的跨平台特性
在class首次从jar中找到对应的文件时
查找的顺序是文件操作系统实现决定
  与inode值无关
 将不同的版本进行打包时,就会出现相应的问题
版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

本文链接: https://www.Java265.com/JavaJingYan/202209/16621039294308.html

最近发表

热门文章

好文推荐

Java265.com

https://www.java265.com

站长统计|粤ICP备14097017号-3

Powered By Java265.com信息维护小组

使用手机扫描二维码

关注我们看更多资讯

java爱好者