The most wonderful six months of work experience problems

The most wonderful six months of work experience problems

background

The company recently bought a project, a series of strange problems on startup, the other's technology stack requirement is Tomcat7 start, but due to our company for safety reasons it is required to start using Tomcat9.

Problem Description

The following are the same as the case of the case where the same war package Tomcat

system Tomcat version Can start
Windows Tomcat7 can
Windows Tomcat9 can
macOS Tomcat7 can
macOS Tomcat9 Can not
Linux Tomcat7 can
Linux Tomcat9 Can not

Due to the project are not familiar with, resulting in a long time to find to find out why. Ali discovery process is to use open source Arthasthat class problems compiler is running out, and found two classes from different Jar package, so the question turned to the loading order of Jar is what factors led.

Issues get to the bottom

Class two with the same name in the path name of the class loader will load only once

This problem occurs when knew check the information, JVM class loader is a tree structure, in the process of loading the JVM parents adopt delegated model, the higher the level, the class loader will load earlier in its path the type. Here is the level of Tomcat class loader is located.


      Bootstrap
          |
       System
          |
       Common
       /     \
  Webapp1   Webapp2 .

复制代码

We know that the problem is two Jar in the same class loader, so ruled out the issue of different levels of class loader caused.

Tomcat7 load Jar package principle

Tomcat to realize his own class loader for loading all class files its own local project jar package, so in the same class loader, if there is the same path and class names so the load order is the order jar package to decide. Who advanced to the jar package, then to which class loader.

But why all the Tomcat7 environment are functioning properly, and in Tomcat9 would not be in it? So when you see the Tomcat7 jar package source loaded in the Context of the project

Tomcat7 jar loading portion, in WebappLoader.setRepositories()a method in which the paste important codes.

 // Looking up directory /WEB-INF/lib in the context
    NamingEnumeration<NameClassPair> enumeration = null;
    try {
        //这一句是获得jar包的路径
        enumeration = libDir.list("");
    } catch (NamingException e) {
        IOException ioe = new IOException(sm.getString(
                "webappLoader.namingFailure", libPath));
        ioe.initCause(e);
        throw ioe;
    }

复制代码

list path is obtained under application WEB-INF lib at all a jar. We track go find FileDirContextthe list method has the following sentence

Arrays.sort(names);             // Sort alphabetically

复制代码

We can be found in the Tomcat7 made a sort of action to get all the jar packages. To jar packets initials az sorted. And we expect that the loaded jar package initials just in the wrong jar package earlier.

Tomcat9 load Jar package principle

Above we know why Tomcat7 able to start up in all the projects, because Tomcat7 made a sort of action, then when Tomcat9 load Jar package, but also how to do it?

Tomcat9 when the source is loaded by StandardRoot.processWebInfLib()loading method

    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(), "/");
            }
        }
    }

复制代码

In this we can see that Tomcat did not make any moves to Jar taken out, just File file = new File()so it traverses out. So why the same Tomcat9 same War in Windos can start up package, but in macOS and Linux are not started up yet? After testing found that Java access to the folder all of the following documents are related with the operating system's file system, the same folder contents, taken out in Windows, the name of the output you will find that the output is the result of az sorted, but in macOS or Linux, you can command ll -fican output the natural order, you will find that there is no law at all.

solve

To all the problems described above, here we can explain through, and how the next step was resolved.

  1. Tomcat9 modified source code, Jar package to get all of the time, to sort it
  2. To get rid of files with conflicts

The first solution can only solve the problem temporarily, that the project can start up normally, but then once it comes to the modification of related classes, then the class conflict which class it? Then the problem is definitely a time bomb.

After the second option is to find files that have conflicts, and then do not find that to be deleted, but found a deletion would pop out the other, removed several items found due to buy the code is not standardized, so this phenomenon particularly, if a simple screening by hand, then extremely troublesome. So I wrote a script ran out project files for all classes of the same name.

Script ideas

  1. Find all the Java files
  2. Java files found on packagethat line, then read this line
  3. packageThe back of the package name and class name spliced ​​into the collection List
  4. We screened the same set of content

Specific script code can go to GitHub to see in. Use simple instructions, the whole project code you want to scan in a folder, for example, I want to scan A, B, C, D four projects.

--/
  --scanDir
   --A
   --B
   --C
   --D

复制代码

So I just Jar package introduced after the call with the following

List<String> list = FindDuplicate.findDuplicatePath("/scanDir/");

复制代码

Is a collection of returned record indicates a conflict has set a file, the file path conflicts are two ||||||||spaced

Script code

Past articles on Tomcat

Guess you like

Origin juejin.im/post/5d0365725188251cdb082563
Recommended