Поведение Classloader на Tomcat с несколькими приложениями

На сервере Tomcat 5.5 я поместил класс в системный путь к классу (и измените catalina.bat для выбора его), или если я поместил класс в общий каталог lib. Теперь, если у меня есть два различных приложения с помощью того же класса, которые не имеют класса в их ВЕБ-INF каталогах lib/классов, они используют тот же экземпляр класса. Я понимаю понятие, к которому делегирует classloader, он - родитель classloader для нахождения класса, если это не может найти его, так в этом случае, так как класс не присутствует в WEB-INF/classes или WEB-INF/lib, WebAppX classloader попробует общее, общее и систему classloader соответственно.

Однако это так или иначе кажется странным мне, что два различных приложения могут совместно использовать контекст с помощью этого метода. Мог кто-то помогать мне понять, почему это так. например, в ниже кода эти два сервлета каждый развертываются в отдельных войнах, в то время как CommonCounter совместно используется, и они могут считать встречные значения, увеличенные другим.

Править

Это кажется парадоксальным мне, что два отдельных приложения могут совместно использовать контекст этим способом. На самом деле, если у них есть тот же экземпляр класса, они могут даже реализовать многопоточность/синхронизацию через два различных приложения, которая кажется чрезвычайно парадоксальной.

package com.test;
public class CommonCounter {

    public static int servlet1;
    public static int servlet2;
}




public class Servlet1 extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        CommonCounter.servlet1++;
        System.out.println("Other one had "+CommonCounter.servlet2+" hits");
    }   
}



public class Servlet2 extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        CommonCounter.servlet2++;
        System.out.println("Other one had "+CommonCounter.servlet1+" hits");
    }   
}
13
задан Hearen 20 March 2019 в 01:13
поделиться

1 ответ

Как говорится в комментариях, вы правильно объяснили, почему вы наблюдали такое поведение.

Ключ в том, как устроены загрузчики классов. Вполне возможно, чтобы два ClassLoader в одной JVM загружали каждый класс и, следовательно, содержали отдельные независимые копии статических полей. «static» делает что-то «глобальным» для ClassLoader, а не для JVM. Я полагаю, Tomcat не мог удерживать ClassLoader на уровне контейнера с разделяемыми библиотеками и каким-то образом заставлять каждое приложение ClassLoader загружать разделяемые библиотеки отдельно.

Но это было бы немного расточительно для других распространенных классов, таких как J2EE API и реализация. И, в принципе, классы в любом случае не должны зависеть от этой структуры ClassLoader.

Вот почему вам не следует помещать зависимости приложений в папки общей библиотеки Tomcat. Это «решение». Он связывает ваше приложение с настройкой и развертыванием конкретного контейнера, что противоречит принципу веб-приложений J2EE. Просто поместите копии зависимостей в WEB-INF / lib для каждого приложения.

Наблюдаемое вами поведение - еще одна причина не делать этого: приложения становятся менее изолированными друг от друга. Это не кажется мне противоречащим интуиции поведением, но я полагаю, это просто потому, что я привык к тому, как работает Tomcat, и думаю об этих вещах.

12
ответ дан 2 December 2019 в 00:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: