This commit is contained in:
2024-11-30 19:03:49 +08:00
commit 1e6763c160
3806 changed files with 737676 additions and 0 deletions

View File

@@ -0,0 +1,26 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.loader;
public class Constants {
public static final String Package = "org.apache.catalina.loader";
}

View File

@@ -0,0 +1,77 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.loader;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
/**
* This class is loaded by {@link WebappClassLoaderBase} to enable it to
* deregister JDBC drivers forgotten by the web application. There are some
* classloading hacks involved - see
* {@link WebappClassLoaderBase#clearReferences()} for details - but the short
* version is do not just create a new instance of this class with the new
* keyword.
*
* Since this class is loaded by {@link WebappClassLoaderBase}, it cannot refer
* to any internal Tomcat classes as that will cause the security manager to
* complain.
*/
public class JdbcLeakPrevention {
public List<String> clearJdbcDriverRegistrations() throws SQLException {
List<String> driverNames = new ArrayList<>();
/*
* DriverManager.getDrivers() has a nasty side-effect of registering
* drivers that are visible to this class loader but haven't yet been
* loaded. Therefore, the first call to this method a) gets the list
* of originally loaded drivers and b) triggers the unwanted
* side-effect. The second call gets the complete list of drivers
* ensuring that both original drivers and any loaded as a result of the
* side-effects are all de-registered.
*/
HashSet<Driver> originalDrivers = new HashSet<>();
Enumeration<Driver> drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
originalDrivers.add(drivers.nextElement());
}
drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
Driver driver = drivers.nextElement();
// Only unload the drivers this web app loaded
if (driver.getClass().getClassLoader() !=
this.getClass().getClassLoader()) {
continue;
}
// Only report drivers that were originally registered. Skip any
// that were registered as a side-effect of this code.
if (originalDrivers.contains(driver)) {
driverNames.add(driver.getClass().getCanonicalName());
}
DriverManager.deregisterDriver(driver);
}
return driverNames;
}
}

View File

@@ -0,0 +1,62 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
webappClassLoader.addExportsRmi=When running on Java 9 you need to add "--add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED" to the JVM command line arguments to enable RMI Target memory leak detection. Alternatively, you can suppress this warning by disabling RMI Target memory leak detection.
webappClassLoader.addExportsThreadLocal=When running on Java 9 you need to add "--add-opens=java.base/java.lang=ALL-UNNAMED" to the JVM command line arguments to enable ThreadLocal memory leak detection. Alternatively, you can suppress this warning by disabling ThreadLocal memory leak detection.
webappClassLoader.addPermisionNoCanonicalFile=Unable to obtain a canonical file path from the URL [{0}]
webappClassLoader.addPermisionNoProtocol=The protocol [{0}] in the URL [{1}] is not supported so no read permission was granted for resources located at this URL
webappClassLoader.addTransformer=Added class file transformer [{0}] to web application [{1}].
webappClassLoader.addTransformer.duplicate=Duplicate call to add class file transformer [{0}] to web application [{1}] ignored.
webappClassLoader.addTransformer.illegalArgument=The web application [{0}] attempted to add a null class file transformer.
webappClassLoader.checkThreadLocalsForLeaks=The web application [{0}] created a ThreadLocal with key of type [{1}] (value [{2}]) and a value of type [{3}] (value [{4}]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
webappClassLoader.checkThreadLocalsForLeaks.badKey=Unable to determine string representation of key of type [{0}]
webappClassLoader.checkThreadLocalsForLeaks.badValue=Unable to determine string representation of value of type [{0}]
webappClassLoader.checkThreadLocalsForLeaks.unknown=Unknown
webappClassLoader.checkThreadLocalsForLeaksFail=Failed to check for ThreadLocal references for web application [{0}]
webappClassLoader.checkThreadLocalsForLeaksNone=The web application [{0}] created a ThreadLocal with key of type [{1}] (value [{2}]) and a value of type [{3}] (value [{4}]). Since keys are only weakly held by the ThreadLocal Map this is not a memory leak.
webappClassLoader.checkThreadLocalsForLeaksNull=The web application [{0}] created a ThreadLocal with key of type [{1}] (value [{2}]). The ThreadLocal has been correctly set to null and the key will be removed by GC.
webappClassLoader.checkThreadsHttpClient=Found HttpClient keep-alive thread using web application class loader. Fixed by switching thread to the parent class loader.
webappClassLoader.clearJdbc=The web application [{0}] registered the JDBC driver [{1}] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
webappClassLoader.clearObjectStreamClassCachesFail=Failed to clear soft references from ObjectStreamClass$Caches for web application [{0}]
webappClassLoader.clearRmi=Found RMI Target with stub class class [{0}] and value [{1}]. This RMI Target has been forcibly removed to prevent a memory leak.
webappClassLoader.clearRmiFail=Failed to clear context class loader referenced from sun.rmi.transport.Target for web application [{0}]
webappClassLoader.clearRmiInfo=Failed to find class sun.rmi.transport.Target to clear context class loader for web application [{0}]. This is expected on non-Sun JVMs.
webappClassLoader.getThreadGroupError=Unable to obtain the parent for ThreadGroup [{0}]. It will not be possible to check all threads for potential memory leaks
webappClassLoader.jarsAdded=One or more JARs have been added to the web application [{0}]
webappClassLoader.jarsModified=One or more JARs have been modified in the web application [{0}]
webappClassLoader.jarsRemoved=One or more JARs have been removed from the web application [{0}]
webappClassLoader.javaseClassLoaderNull=The j2seClassLoader attribute may not be null
webappClassLoader.jdbcRemoveFailed=JDBC driver de-registration failed for web application [{0}]
webappClassLoader.loadedByThisOrChildFail=Failed to fully check the entries in an instance of [{0}] for potential memory leaks in context [{1}]
webappClassLoader.readError=Resource read error: Could not load [{0}].
webappClassLoader.removeTransformer=Removed class file transformer [{0}] from web application [{1}].
webappClassLoader.resourceModified=Resource [{0}] has been modified. The last modified time was [{1}] and is now [{2}]
webappClassLoader.stackTrace=The web application [{0}] appears to have started a thread named [{1}] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:{2}
webappClassLoader.stackTraceRequestThread=The web application [{0}] is still processing a request that has yet to finish. This is very likely to create a memory leak. You can control the time allowed for requests to finish by using the unloadDelay attribute of the standard Context implementation. Stack trace of request processing thread:[{2}]
webappClassLoader.stopThreadFail=Failed to terminate thread named [{0}] for web application [{1}]
webappClassLoader.stopTimerThreadFail=Failed to terminate TimerThread named [{0}] for web application [{1}]
webappClassLoader.stopped=Illegal access: this web application instance has been stopped already. Could not load [{0}]. The following stack trace is thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access.
webappClassLoader.superCloseFail=Failure calling close() on super class
webappClassLoader.transformError=Instrumentation error: could not transform class [{0}] because its class file format is not legal.
webappClassLoader.warnTimerThread=The web application [{0}] appears to have started a TimerThread named [{1}] via the java.util.Timer API but has failed to stop it. To prevent a memory leak, the timer (and hence the associated thread) has been forcibly canceled.
webappClassLoader.wrongVersion=(unable to load class [{0}])
webappClassLoaderParallel.registrationFailed=Registration of org.apache.catalina.loader.ParallelWebappClassLoader as capable of loading classes in parallel failed
webappLoader.deploy=Deploying class repositories to work directory [{0}]
webappLoader.reloadable=Cannot set reloadable property to [{0}]
webappLoader.setContext.ise=Setting the Context is not permitted while the loader is started.
webappLoader.starting=Starting this Loader
webappLoader.stopping=Stopping this Loader

View File

@@ -0,0 +1,18 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
webappClassLoader.checkThreadLocalsForLeaks.unknown=Unbekannt
webappClassLoader.readError=Fehler beim Lesen einer Ressource: Konnte [{0}] nicht laden
webappClassLoader.superCloseFail=Fehler beim Aufruf von close() auf der Super-Klasse

View File

@@ -0,0 +1,40 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
webappClassLoader.checkThreadLocalsForLeaks=La aplicación web [{0}] creó un ThreadLocal con clave del tipo [{1}] (valor [{2}]) y un valor del tipo [{3}] (valor [{4}]) pero no pudo quitarlo cuando la aplicación web se paró. Los hilos se van a renovar con el tiempo para intentar evitar in posible fallo de memoria.
webappClassLoader.checkThreadLocalsForLeaks.badKey=No puedo determinar la representación de cadena de la clave del tipo [{0}]
webappClassLoader.checkThreadLocalsForLeaks.badValue=No puedo determinar la representación de cadena del valor del tipo [{0}]
webappClassLoader.checkThreadLocalsForLeaks.unknown=Desconocido
webappClassLoader.checkThreadLocalsForLeaksFail=No pude revisar las referencias a ThreadLocal para la aplicación web [{0}]
webappClassLoader.checkThreadLocalsForLeaksNull=La aplicación web [{0}] creó un ThreadLocal con clave del tipo [{1}] (valor [{2}]). El Threadlocal ha sido puesto correctamente a nulo y la clave será qutada por el GC.
webappClassLoader.checkThreadsHttpClient=Hallado hilo keep-alive de HttpClient usando cargador de clase de aplicación web. Fijado por el hilo de conmutación al cargador de la clase padre.
webappClassLoader.clearJdbc=La aplicación web [{0}] registró el conductor JDBC [{1}] pero falló al anular el registro mientras la aplicación web estaba parada. Para prevenir un fallo de memoria, se ha anulado el registro del conductor JDBC por la fuerza.
webappClassLoader.clearRmiFail=No pude limpiar el cargador del contexto de clase referenciado desde sun.rmi.transport.Target para la aplicación web [{0}]
webappClassLoader.clearRmiInfo=No pude hallar la clase sun.rmi.transport.Target para limpiar el cargador de contexto de clase para la aplicación web [{0}]. Esto es lo esperado em máquinas que no son de Sun.
webappClassLoader.jarsRemoved=Uno o más JARs han sido eliminados de la aplicación web [{0}]\n
webappClassLoader.jdbcRemoveFailed=Ha fallado el desregistro del conductor JDBC para la aplicación web [{0}]
webappClassLoader.readError=Error de lectura de recurso: No pude cargar [{0}].
webappClassLoader.stopThreadFail=No pude terminar el hilo con nombre [{0}] para la aplicación web [{1}]
webappClassLoader.stopTimerThreadFail=No pude terminar TimerThread con nombre [{0}] para la aplicación web [{1}]
webappClassLoader.stopped=Acceso ilegal: esta instancia de aplicación web ya ha sido parada. Could not load [{0}]. La eventual traza de pila que sigue ha sido motivada por un error lanzado con motivos de depuración así como para intentar terminar el hilo que motivó el acceso ilegal y no tiene impacto funcional.
webappClassLoader.superCloseFail=Fallo a llamar close() en la clase super
webappClassLoader.warnTimerThread=La aplicación web [{0}] parece haber arrancado un TimerThread con nombre [{1}] vía de la API java.util.Timer, pero no ha podido pararlo. Para prevenir un fallo de memoria, el cronómetro (y el hilo asociado) hasido cancelado a la fuerza.
webappClassLoader.wrongVersion=(no puedo cargar clase [{0}])
webappLoader.deploy=Desplegando repositorios de clase en directorio de trabajo [{0}]
webappLoader.reloadable=No puedo poner la propiedad recargable a [{0}]
webappLoader.setContext.ise=No esta permitido fijar el Contexto mientras el cargador esta iniciado.\n
webappLoader.starting=Arrancando este Cargador
webappLoader.stopping=Parando este Cargador

View File

@@ -0,0 +1,62 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
webappClassLoader.addExportsRmi=Quand Java 9 est utilisé, il faut utiliser "--add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED" sur la ligne de commande de la JVM pour activer la détection de fuites de mémoire des cibles RMI; sinon cet avertissement peut être supprimé en désactivant cette détection
webappClassLoader.addExportsThreadLocal=Quand Java 9 est utilisé, il faut utiliser "--add-opens=java.base/java.lang=ALL-UNNAMED" sur la ligne de commande de la JVM pour activer la détection de fuites de mémoire des ThreadLocal; sinon cet avertissement peut être supprimé en désactivant cette détection
webappClassLoader.addPermisionNoCanonicalFile=Impossible dobtenir le chemin de fichier canonique pour l''URL [{0}]
webappClassLoader.addPermisionNoProtocol=Le protocole [{0}] dans l''URL [{1}] n''est pas supporté donc aucune permission de lecture n''a été assignée pour les ressources situées à cette URL
webappClassLoader.addTransformer=Ajout d''un transformateur de fichier de class [{0}] pour l''application web [{1}]
webappClassLoader.addTransformer.duplicate=Ajout en double ignoré du transformateur de fichiers de classe [{0}] à l''application web [{1}]
webappClassLoader.addTransformer.illegalArgument=L''application web [{0}] a essayé d''ajouter un transformateur de fichiers de classe null
webappClassLoader.checkThreadLocalsForLeaks=L''application web [{0}] a crée un ThreadLocal avec une clé de type [{1}] (valeur [{2}]) et une valeur de type [{3}] (valeur [{4}]) mais ne l''a pas supprimé lorsqu''elle a été arrêtée, les threads seront graduellement renouvelés pour éviter une probable fuite de mémoire
webappClassLoader.checkThreadLocalsForLeaks.badKey=Impossible de déterminer une représentation sous forme de chaîne de caractères d''une clé du type [{0}]
webappClassLoader.checkThreadLocalsForLeaks.badValue=Impossible de déterminer la représentation sous forme de chaîne de caractère de la valeur du type [{0}]
webappClassLoader.checkThreadLocalsForLeaks.unknown=Inconnu
webappClassLoader.checkThreadLocalsForLeaksFail=Echec de vérfication des références ThreadLocal pour l''application web [{0}]
webappClassLoader.checkThreadLocalsForLeaksNone=L''application web [{0}] a crée un ThreadLocal avec une clé de type [{1}] (valeur [{2}]) et une valeur de type [{3}] (valeur [{4}]) mais comme les clés n''ont que des références faibles dans la structure des ThreadLocal cela ne causera pas de fuite de mémoire
webappClassLoader.checkThreadLocalsForLeaksNull=L''application web [{0}] a crée un ThreadLocal avec une clé de type [{1}] (valeur [{2}]), ce ThreadLocal a correctement été fixé à null et la valeur sera enlevée par la GC
webappClassLoader.checkThreadsHttpClient=Trouvé une thread utilisé par HttpClient pour maintenir les connections actives, corrigé en associant le thread avec le chargeur de classe parent
webappClassLoader.clearJdbc=L''application web [{0}] a enregistré un pilote JDBC [{1}], mais ne l''a pas désenregistré avant l''arrêt de l''application. Pour éviter une fuite de mémoire, le pilote JDBC a été désenregistré de force.
webappClassLoader.clearObjectStreamClassCachesFail=Impossible d''effacer les références faibles de ObjectStreamClass$Caches pour l''application web [{0}]
webappClassLoader.clearRmi=Trouvé une cible RMI avec une classe squelette de classe [{0}] et une valeur [{1}], celle ci a été enlevée de force pour prévenir ue fuite de mémoir
webappClassLoader.clearRmiFail=Impossible d''effacer le chargeur de classes de contexte référencé depuis sun.rmi.transport.Target pour l''application web [{0}]
webappClassLoader.clearRmiInfo=Impossible de trouver la classe sun.rmi.transport.Target pour nettoyer le chargeur de classes du contexte pour l''application web [{0}], c''est normal pour les JVMs non Oracle
webappClassLoader.getThreadGroupError=Impossible d''obtenir le parent pour le ThreadGroup [{0}], il ne sera pas possible de vérifier tous les threads pour des fuites de mémoire
webappClassLoader.jarsAdded=Un ou plusieurs JARs ont été ajoutés à l''application web [{0}]
webappClassLoader.jarsModified=Un ou plusieurs JARs ont été modifiés dans l''application web [{0}]
webappClassLoader.jarsRemoved=Un ou plusieurs JARs ont été enlevés de l''application web [{0}]
webappClassLoader.javaseClassLoaderNull=L'attribut j2seClassLoader ne doit pas être null
webappClassLoader.jdbcRemoveFailed=Le désenregistrement du pilote JDBC a échoué pour l''application web [{0}]
webappClassLoader.loadedByThisOrChildFail=Impossible de vérifier complètement les entrées d''une instance de [{0}] pour des fuites de mémoire potentielles dans le contexte [{1}]
webappClassLoader.readError=Erreur lors de la lecture de la resource : impossible de charger [{0}].
webappClassLoader.removeTransformer=Enlevé le transformateur de fichiers de classe [{0}] de l''application web [{1}]
webappClassLoader.resourceModified=La ressource [{0}] a été modifiée, la date de dernière modification était [{1}] et est désormais [{2}]
webappClassLoader.stackTrace=L''application web [{0}] semble avoir démarré un thread nommé [{1}] mais ne l''a pas arrêté, ce qui va probablement créer une fuite de mémoire; la trace du thread est: {2}
webappClassLoader.stackTraceRequestThread=Une requête de l''application web [{0}] est toujours en cours, ce qui causera certainement une fuite de mémoire, vous pouvez contrôler le temps alloué en utilisant l''attribut unloadDelay de l''implémentation standard de Context; trace du fil dexécution de la requête: [{2}]
webappClassLoader.stopThreadFail=Impossible de terminer le thread nommé [{0}] pour l''application [{1}]
webappClassLoader.stopTimerThreadFail=Echec de l''arrêt du TimerThread nommé [{0}] pour l''application web [{1}]
webappClassLoader.stopped=Impossible de charger [{0}], ce chargeur de classes a déjà été arrêté
webappClassLoader.superCloseFail=Echec lors de l'appel de close() dans la superclasse
webappClassLoader.transformError=Erreur d''instrumentation: impossible de transformer la classe [{0}] parce que son format est illégal
webappClassLoader.warnTimerThread=L''application [{0}] semble avoir démarré un TimerThread nommé [{1}] en utilisant java.util.Timer mais ne l''a pas stoppé, le timer ainsi que le thread associé ont été arrêtés pour éviter une fuite de mémoire
webappClassLoader.wrongVersion=(impossible de charger la classe [{0}])
webappClassLoaderParallel.registrationFailed=L'enregistrement de org.apache.catalina.loader.ParallelWebappClassLoader comme pouvant charger des classes en parallèle a échoué
webappLoader.deploy=Déploiement des classes des réceptacles (class repositories) vers le répertoire de travail [{0}]
webappLoader.reloadable=Impossible de mettre la propriété rechargeable à [{0}]
webappLoader.setContext.ise=Il est interdit de définir le Context lorsque le chargeur de classes a déjà été démarré
webappLoader.starting=Démarrage de ce chargeur (loader)
webappLoader.stopping=Arrêt de ce chargeur (loader)

View File

@@ -0,0 +1,62 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
webappClassLoader.addExportsRmi=Java 9で実行する場合は、JVMコマンドライン引数に "--add-opens = java.rmi / sun.rmi.transport = ALL-UNNAMED"を追加して、RMIターゲットメモリリーク検出を有効にする必要があります。 また、RMIターゲットメモリリーク検出を無効にすることで、この警告を抑制することも可能です。
webappClassLoader.addExportsThreadLocal=Java 9で実行する場合は、JVMコマンドライン引数に "--add-opens = java.base / java.lang = ALL-UNNAMED"を追加して、ThreadLocalメモリリーク検出を有効にする必要があります。 また、ThreadLocalメモリリーク検出を無効にすることで、この警告を抑制することもできます。
webappClassLoader.addPermisionNoCanonicalFile=URL [{0}] の正規化パスを取得できません。
webappClassLoader.addPermisionNoProtocol=URL [{1}] に含まれるプロトコル [{0}] は未対応です。この URL で参照できるリソースには読み取り権限を付与できません。
webappClassLoader.addTransformer=Web アプリケーション [{1}] にクラスファイル変換器 [{0}] を追加しました。
webappClassLoader.addTransformer.duplicate=クラスファイルトランスフォーマー[{0}]をWebアプリケーション[{1}]に追加する呼び出しが重複しました。
webappClassLoader.addTransformer.illegalArgument=Webアプリケーション[{0}]がNullクラスファイルトランスフォーマーを追加しようとしました。
webappClassLoader.checkThreadLocalsForLeaks=Webアプリケーション[{0}]はタイプ[{1}](値[{2}])のキーと値タイプ[{3}](値[{4}]のThreadLocalを作成しましたが、 それはWebアプリケーションの停止時に削除されていません。スレッドは時間の経過とともに更新され、メモリリークの可能性を回避しようとしています。
webappClassLoader.checkThreadLocalsForLeaks.badKey=キー値のクラス [{0}] の文字列表現を取得できません。
webappClassLoader.checkThreadLocalsForLeaks.badValue=クラス [{0}] の文字列表現を取得できません。
webappClassLoader.checkThreadLocalsForLeaks.unknown=不明
webappClassLoader.checkThreadLocalsForLeaksFail=Webアプリケーション[{0}]のThreadLocal参照を確認できませんでした。
webappClassLoader.checkThreadLocalsForLeaksNone=Web アプリケーション [{0}] はキー [{1}] (値は [{1}])、値 [{3}](値は [{4}])をスレッドローカルに作成しました。キーは ThreadLocalMap の弱参照として保持されるため、メモリーリークではありません。
webappClassLoader.checkThreadLocalsForLeaksNull=Webアプリケーション[{0}]はタイプ[{1}](値[{2}]のキーを持つThreadLocalを作成しました。 ThreadLocalは正しくnullに設定され、キーはGCによって削除されます。
webappClassLoader.checkThreadsHttpClient=Webアプリケーションクラスローダーを使用しているHttpClientキープアライブスレッドを検出しました。 スレッドを親クラスローダに切り替えることで修正されました。
webappClassLoader.clearJdbc=Web アプリケーション [{0}] は自身で登録した JDBC ドライバー [{1}] を停止時に解除できませんでした。メモリーリークの発生を防ぐには JDBC ドライバーを強制的に解除してください。
webappClassLoader.clearObjectStreamClassCachesFail=Web アプリケーション [{0}] の ObjectStreamClass$Caches についてソフト参照を除去できません。
webappClassLoader.clearRmi=クラス [{0}] 値 [{1}] のスタブクラスを持つ RMI ターゲットを発見しました。メモリーリークを防ぐため発見した RMI ターゲットは強制的に削除します。
webappClassLoader.clearRmiFail=Webアプリケーション[{0}]のsun.rmi.transport.Targetから参照されるコンテキストクラスローダーのクリアに失敗しました。
webappClassLoader.clearRmiInfo=Web アプリケーション [{0}] のコンテキストクラスローダーをきれいにするための sun.rmi.transport.Target クラスが見つかりません。Sun 以外の JVM で実行している可能性があります。
webappClassLoader.getThreadGroupError=スレッドグループ [{0}] の親スレッドグループを取得できません。潜在的なメモリリークをすべてのスレッドでチェックすることはできません。
webappClassLoader.jarsAdded=1つ以上のJARがWebアプリケーション[{0}]に追加されました。
webappClassLoader.jarsModified=1つ以上のJARがWebアプリケーション[{0}]で変更されました。
webappClassLoader.jarsRemoved=Web アプリケーション [{0}] から 1 つ以上の JAR が削除されました。
webappClassLoader.javaseClassLoaderNull=j2seClassLoader属性はnullでない場合があります。
webappClassLoader.jdbcRemoveFailed=Web アプリケーション [{0}] は JDBC ドライバーの登録を解除できません。
webappClassLoader.loadedByThisOrChildFail=クラス [{0}] のインスタンスの全ての要素をチェックできませんでした。コンテキスト [{1}] でメモリーリークの発生する可能性があります。
webappClassLoader.readError=リソースの読み込みに失敗: [{0}] が読み込めませんでした。
webappClassLoader.removeTransformer=クラスファイル変換器 [{0}] を Web アプリケーション [{1}] から削除しました。
webappClassLoader.resourceModified=リソース [{0}] は変更されています。直前の更新日時は [{1}]、最新の更新日時は [{2}] です。
webappClassLoader.stackTrace=Webアプリケーション[{0}]は[{1}]という名前のスレッドを開始したようですが、停止に失敗しました。 これはメモリリークを引き起こす可能性が非常に高いです。 スレッドのスタックトレース:{2}
webappClassLoader.stackTraceRequestThread=Webアプリケーション[{0}]はまだ完了していないリクエストを処理しています。 これはメモリリークを引き起こす可能性が非常に高いです。 リクエストの終了時間は、StandardContext実装のunloadDelay属性を使用して制御できます。 陸絵鵜sと処理スレッドのスタックトレース[{2}]
webappClassLoader.stopThreadFail=Web アプリケーション [{1}] のスレッド [{0}] は終了できません。
webappClassLoader.stopTimerThreadFail=Webアプリケーション[{1}]の[{0}]という名前のTimerThreadを終了できませんでした。
webappClassLoader.stopped=不正なアクセス: このWebアプリケーションのインスタンスは既に停止されています Could not load [{0}]. 不正なアクセスを引き起こしたスレッドを終了させ、投げられたエラーによりデバッグ用に次のスタックトレースが生成されましたが,機能に影響はありません
webappClassLoader.superCloseFail=基底クラスで close() の呼び出しに失敗しました。
webappClassLoader.transformError=計測エラー:クラスファイル形式が正当でないため、クラス[{0}]を変換できませんでした。
webappClassLoader.warnTimerThread=Web アプリケーション [{0}] が java.util.Timer API で開始した TimerThread [{1}] を停止できません。メモリーリークを防ぐにはタイマー(関連付けられたスレッドも)を強制的にキャンセルしてください。
webappClassLoader.wrongVersion=(クラス[{0}]をロードできません)
webappClassLoaderParallel.registrationFailed=並列にクラスをロードできるorg.apache.catalina.loader.ParallelWebappClassLoaderの登録に失敗しました。
webappLoader.deploy=クラスリポジトリを作業ディレクトリ [{0}] に配備します
webappLoader.reloadable=reloadableプロパティを [{0}] に設定できません
webappLoader.setContext.ise=クラスローダーが開始したあとは Context を構成することはできません。
webappLoader.starting=このローダを起動します
webappLoader.stopping=このローダを停止します

View File

@@ -0,0 +1,62 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
webappClassLoader.addExportsRmi=Java 9에서 실행하면서 RMI Target 메모리 누수 탐지를 사용 가능하게 하려면, "--add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED"를 JVM 명령 행 아규먼트에 추가해야 합니다. 또는, RMI Target 메모리 누수 탐지를 사용불능 상태로 설정함으로써, 이 경고를 없앨 수도 있습니다.
webappClassLoader.addExportsThreadLocal=Java 9 환경에서 실행할 때에는, ThreadLocal 메모리 누수 탐지를 위하여, "--add-opens=java.base/java.lang=ALL-UNNAMED"를 JVM 명령 행 아규먼트들에 추가해야 합니다. 또는, ThreadLocal 메모리 누수 탐지를 사용불능 상태로 설정함으로써, 이 경고 메시지를 없앨 수도 있습니다.
webappClassLoader.addPermisionNoCanonicalFile=URL [{0}](으)로부터 canonical 파일 경로를 얻을 수 없습니다.
webappClassLoader.addPermisionNoProtocol=URL [{1}] 내의 프로토콜 [{0}]은(는) 지원되지 않으므로, 이 URL의 리소스에 대한 읽기가 승인되지 않았습니다.
webappClassLoader.addTransformer=클래스 파일 Transformer [{0}]을(를) 웹 애플리케이션 [{1}]에 추가했습니다.
webappClassLoader.addTransformer.duplicate=웹 애플리케이션 [{1}]에 클래스 파일 변환기 [{0}]을(를) 추가하기 위한, 중복된 호출을 무시합니다.
webappClassLoader.addTransformer.illegalArgument=웹 애플리케이션 [{0}]이(가) 널인, 클래스 파일 Transformer을 추가하려 시도했습니다.
webappClassLoader.checkThreadLocalsForLeaks=웹 애플리케이션 [{0}]이(가), 타입 [{1}]인 키와 (값: [{2}]) 타입 [{3}]인 값을 (값: [{4}]) 사용하여 ThreadLocal 객체를 생성했지만, 웹 애플리케이션이 중지될 때 그것을 제거하지 못했습니다. 혹시 있을 법한 메모리 누수를 방지하기 위하여, 시간을 두고 쓰레드들을 재생성할 것입니다.
webappClassLoader.checkThreadLocalsForLeaks.badKey=타입이 [{0}]인 키의 문자열 representation을 결정할 수 없습니다.
webappClassLoader.checkThreadLocalsForLeaks.badValue=타입이 [{0}]인 값의 문자열 representation을 결정할 수 없습니다.
webappClassLoader.checkThreadLocalsForLeaks.unknown=알 수 없음
webappClassLoader.checkThreadLocalsForLeaksFail=웹 애플리케이션 [{0}]을(를) 위한 ThreadLocal 참조들에 대한 점검이 실패했습니다.
webappClassLoader.checkThreadLocalsForLeaksNone=웹 애플리케이션 [{0}]이(가), 타입 [{1}]의 키(값: [{2}])와 타입 [{3}]의 값(값: [{4}])을 사용하여, ThreadLocal Map을 생성했습니다. 해당 ThreadLocal Map은 weak 키들을 유지하고 있기 때문에, 이는 메모리 누수가 아닙니다.
webappClassLoader.checkThreadLocalsForLeaksNull=웹 애플리케이션 [{0}]이(가), 타입 [{1}]인 키를 (값: [{2}]) 사용하여 ThreadLocal 객체를 생성했습니다. 해당 ThreadLocal 객체가 올바르게 널로 설정되었으므로, 해당 키는 GC에 의해 제거 될 것입니다.
webappClassLoader.checkThreadsHttpClient=웹 애플리케이션 클래스로더를 사용하는 HttpClient keep-alive 쓰레드를 발견했습니다. 쓰레드의 클래스로더를 부모 클래스로더로 전환시켰습니다.
webappClassLoader.clearJdbc=웹 애플리케이션 [{0}]이(가) JDBC 드라이버 [{1}]을(를) 등록했지만, 웹 애플리케이션이 중지될 때, 해당 JDBC 드라이버의 등록을 제거하지 못했습니다. 메모리 누수를 방지하기 위하여, 등록을 강제로 제거했습니다.
webappClassLoader.clearObjectStreamClassCachesFail=웹 애플리케이션 [{0}]을(를) 위해, ObjectStreamClass$Caches로부터 soft references를 폐기하지 못했습니다.
webappClassLoader.clearRmi=스텁 클래스 [{0}]와(과) 값 [{1}]을(를) 가진 RMI Target을 발견했습니다. 이 RMI Target은 메모리 누수를 방지하기 위하여 강제로 제거되었습니다.
webappClassLoader.clearRmiFail=sun.rmi.transport.Target으로부터 참조된 컨텍스트 클래스로더를, 웹 애플리케이션 [{0}]을(를) 위해, 폐기하지 못했습니다.
webappClassLoader.clearRmiInfo=웹 애플리케이션 [{0}]을(를) 위한 컨텍스트 클래스로더를 폐기하기 위한, 클래스 sun.rmi.transport.Target을 찾지 못했습니다. 이는 Sun JVM들이 아닌 환경에서 발생할 수 있습니다.
webappClassLoader.getThreadGroupError=ThreadGroup [{0}]의 부모 ThreadGroup을 얻을 수 없습니다. 잠재적인 메모리 누수 문제를 찾기 위해 모든 쓰레드들을 점검하는 것이 불가능합니다.
webappClassLoader.jarsAdded=하나 이상의 JAR들이 웹 애플리케이션 [{0}]에 추가됐습니다.
webappClassLoader.jarsModified=웹 애플리케이션 [{0}]에서 하나 이상의 JAR 파일(들)이 변경되었습니다.
webappClassLoader.jarsRemoved=하나 이상의 JAR들이 웹 애플리케이션 [{0}](으)로부터 제거되었습니다.
webappClassLoader.javaseClassLoaderNull=j2seClassLoader 속성이 널이어서는 안됩니다.
webappClassLoader.jdbcRemoveFailed=웹 애플리케이션 [{0}]을(를) 위한 JDBC 드라이버의 등록을 제거하지 못했습니다.
webappClassLoader.loadedByThisOrChildFail=컨텍스트 [{1}]에서 잠재적 메모리 누수를 방지하기 위해, [{0}] 클래스의 인스턴스 내에 있는 엔트리들을 모두 점검하려는 시도가 실패했습니다.
webappClassLoader.readError=리소스 읽기 오류 : [{0}]을(를) 로드할 수 없었습니다.
webappClassLoader.removeTransformer=웹 애플리케이션 [{1}](으)로부터 클래스 파일 Transformer [{0}]을(를) 제거했습니다.
webappClassLoader.resourceModified=리소스 [{0}]이(가) 변경된 적이 있습니다. 최종 변경 시간이 [{1}]이었는데, 이제 [{2}](으)로 바뀌었습니다.
webappClassLoader.stackTrace=웹 애플리케이션 [{0}]이(가) [{1}](이)라는 이름의 쓰레드를 시작시킨 것으로 보이지만, 해당 쓰레드를 중지시키지 못했습니다. 이는 메모리 누수를 유발할 가능성이 큽니다. 해당 쓰레드의 스택 트레이스:{2}
webappClassLoader.stackTraceRequestThread=웹 애플리케이션 [{0}]이(가) 여전히 완료되지 않은 요청을 처리하고 있습니다. 이는 메모리 누수를 유발할 가능성이 높습니다. 표준 컨텍스트 구현의 unloadDelay 속성을 이용하여, 요청 완료 허용 시간을 통제할 수 있습니다. 요청 처리 쓰레드의 스택 트레이스:[{2}]
webappClassLoader.stopThreadFail=웹 애플리케이션 [{1}]을 위한, [{0}](이)라는 이름의 쓰레드를 종료시키지 못했습니다.
webappClassLoader.stopTimerThreadFail=웹 애플리케이션 [{1}]을(를) 위한, [{0}](이)라는 이름의 TimerThread를 종료시키지 못했습니다.
webappClassLoader.stopped=불허되는 접근: 이 웹 애플리케이션 인스턴스는 이미 중지되었습니다. [{0}]을(를) 로드할 수 없습니다. 디버그 목적 및 불허되는 접근을 발생시킨 해당 쓰레드를 종료시키기 위한 시도로서, 다음 스택 트레이스가 생성됩니다.
webappClassLoader.superCloseFail=부모 클래스의 close() 호출 시 실패 발생
webappClassLoader.transformError=Instrumentation 오류: 클래스 파일 포맷이 규약을 따르지 않기 때문에, 클래스 [{0}]을(를) 변환시킬 수 없었습니다.
webappClassLoader.warnTimerThread=웹 애플리케이션 [{0}]이(가) java.util.Timer API를 통해 [{1}](이)라는 이름을 가진 TimerThread를 시작한 것으로 보이지만, 그 쓰레드를 중지시키지 못했습니다. 메모리 누수를 방지하기 위해, 타이머가 (연관된 쓰레드와 함께) 강제로 취소되었습니다.
webappClassLoader.wrongVersion=(클래스 [{0}]을(를) 로드할 수 없습니다)
webappClassLoaderParallel.registrationFailed=org.apache.catalina.loader.ParallelWebappClassLoader를 병렬 클래스 로딩이 가능하게 등록하려 했지만 실패했습니다.
webappLoader.deploy=작업 디렉토리 [{0}]에 클래스 레파지토리들을 배치합니다.
webappLoader.reloadable=reloadable 프로퍼티를 [{0}](으)로 설정할 수 없습니다.
webappLoader.setContext.ise=웹 애플리케이션 로더가 시작되고 있는 동안, 컨텍스트를 설정하는 것은 허용되지 않습니다.
webappLoader.starting=이 로더를 시작합니다.
webappLoader.stopping=이 로더를 중지시키는 중

View File

@@ -0,0 +1,16 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
webappClassLoader.checkThreadLocalsForLeaks.unknown=Неизвестно

View File

@@ -0,0 +1,33 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
webappClassLoader.addTransformer=将类文件转换器[{0}]添加到Web应用程序[{1}]。
webappClassLoader.addTransformer.illegalArgument=Web应用程序[{0}]试图添加空类文件转换器。
webappClassLoader.checkThreadLocalsForLeaks.badValue=无法确定类型为 [{0}] 的值的字符串表示形式
webappClassLoader.checkThreadLocalsForLeaks.unknown=:)未知
webappClassLoader.checkThreadLocalsForLeaksNone=web应用程序 [{0}] 创建了1个ThreadLocal变量(键:[{2}] (类型[{1}]) ,值:[{4}](类型[{3}]) )。键仅被ThreadLocal Map弱引用所以不是内存泄露。
webappClassLoader.clearJdbc=Web应用程序 [{0}] 注册了JDBC驱动程序 [{1}]但在Web应用程序停止时无法注销它。 为防止内存泄漏JDBC驱动程序已被强制取消注册。
webappClassLoader.getThreadGroupError=无法获得线程组[{0}]的父级。不可能检查所有线程是否存在潜在的内存泄漏。
webappClassLoader.jarsRemoved=一个或多个 JAR 已被从 Web 应用程序 [{0}] 中删除
webappClassLoader.jdbcRemoveFailed=Web应用程序 [{0}] 的JDBC驱动程序注销失败
webappClassLoader.readError=资源读取错误:不能加载 [{0}].
webappClassLoader.stackTrace=Web应用程序[{0}]似乎启动了一个名为[{1}]的线程,但未能停止它。这很可能会造成内存泄漏。线程的堆栈跟踪:[{2}]
webappClassLoader.stopped=非法访问此Web应用程序实例已停止。无法加载[{0}]。为了调试以及终止导致非法访问的线程,将抛出以下堆栈跟踪。
webappClassLoader.superCloseFail=调用父类的close()方法出现异常。
webappClassLoader.transformError=检测错误:无法转换类[{0}],因为它的类文件格式是不合法的。
webappClassLoader.warnTimerThread=Web应用程序[{0}]似乎已通过java.util.Timer API启动了名为[{1}]的TimerThread但未能将其停止。 为防止内存泄漏,计时器(以及相关联的线程)已被强制取消。
webappClassLoader.wrongVersion=(无法载入的.类 [{0}])
webappLoader.setContext.ise=当加载器启动的时候设置上下文是不被允许的

View File

@@ -0,0 +1,74 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.loader;
import org.apache.catalina.LifecycleException;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
public class ParallelWebappClassLoader extends WebappClassLoaderBase {
private static final Log log = LogFactory.getLog(ParallelWebappClassLoader.class);
static {
boolean result = ClassLoader.registerAsParallelCapable();
if (!result) {
log.warn(sm.getString("webappClassLoaderParallel.registrationFailed"));
}
}
public ParallelWebappClassLoader() {
super();
}
public ParallelWebappClassLoader(ClassLoader parent) {
super(parent);
}
/**
* Returns a copy of this class loader without any class file
* transformers. This is a tool often used by Java Persistence API
* providers to inspect entity classes in the absence of any
* instrumentation, something that can't be guaranteed within the
* context of a {@link java.lang.instrument.ClassFileTransformer}'s
* {@link java.lang.instrument.ClassFileTransformer#transform(ClassLoader,
* String, Class, java.security.ProtectionDomain, byte[]) transform} method.
* <p>
* The returned class loader's resource cache will have been cleared
* so that classes already instrumented will not be retained or
* returned.
*
* @return the transformer-free copy of this class loader.
*/
@Override
public ParallelWebappClassLoader copyWithoutTransformers() {
ParallelWebappClassLoader result = new ParallelWebappClassLoader(getParent());
super.copyStateWithoutTransformers(result);
try {
result.start();
} catch (LifecycleException e) {
throw new IllegalStateException(e);
}
return result;
}
}

View File

@@ -0,0 +1,38 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.loader;
/**
* Resource entry.
*
* @author Remy Maucherat
*/
public class ResourceEntry {
/**
* The "last modified" time of the origin file at the time this resource
* was loaded, in milliseconds since the epoch.
*/
public long lastModified = -1;
/**
* Loaded class.
*/
public volatile Class<?> loadedClass = null;
}

View File

@@ -0,0 +1,73 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.loader;
import org.apache.catalina.LifecycleException;
public class WebappClassLoader extends WebappClassLoaderBase {
public WebappClassLoader() {
super();
}
public WebappClassLoader(ClassLoader parent) {
super(parent);
}
/**
* Returns a copy of this class loader without any class file
* transformers. This is a tool often used by Java Persistence API
* providers to inspect entity classes in the absence of any
* instrumentation, something that can't be guaranteed within the
* context of a {@link java.lang.instrument.ClassFileTransformer}'s
* {@link java.lang.instrument.ClassFileTransformer#transform(ClassLoader,
* String, Class, java.security.ProtectionDomain, byte[]) transform} method.
* <p>
* The returned class loader's resource cache will have been cleared
* so that classes already instrumented will not be retained or
* returned.
*
* @return the transformer-free copy of this class loader.
*/
@Override
public WebappClassLoader copyWithoutTransformers() {
WebappClassLoader result = new WebappClassLoader(getParent());
super.copyStateWithoutTransformers(result);
try {
result.start();
} catch (LifecycleException e) {
throw new IllegalStateException(e);
}
return result;
}
/**
* This class loader is not parallel capable so lock on the class loader
* rather than a per-class lock.
*/
@Override
protected Object getClassLoadingLock(String className) {
return this;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,665 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.loader;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.File;
import java.io.FilePermission;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.net.URL;
import java.net.URLClassLoader;
import javax.management.ObjectName;
import javax.servlet.ServletContext;
import org.apache.catalina.Context;
import org.apache.catalina.Globals;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleState;
import org.apache.catalina.Loader;
import org.apache.catalina.util.LifecycleMBeanBase;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.buf.UDecoder;
import org.apache.tomcat.util.modeler.Registry;
import org.apache.tomcat.util.res.StringManager;
/**
* Classloader implementation which is specialized for handling web
* applications in the most efficient way, while being Catalina aware (all
* accesses to resources are made through
* {@link org.apache.catalina.WebResourceRoot}).
* This class loader supports detection of modified
* Java classes, which can be used to implement auto-reload support.
* <p>
* This class loader is configured via the Resources children of its Context
* prior to calling <code>start()</code>. When a new class is required,
* these Resources will be consulted first to locate the class. If it
* is not present, the system class loader will be used instead.
*
* @author Craig R. McClanahan
* @author Remy Maucherat
*/
public class WebappLoader extends LifecycleMBeanBase
implements Loader, PropertyChangeListener {
// ----------------------------------------------------------- Constructors
/**
* Construct a new WebappLoader with no defined parent class loader
* (so that the actual parent will be the system class loader).
*/
public WebappLoader() {
this(null);
}
/**
* Construct a new WebappLoader with the specified class loader
* to be defined as the parent of the ClassLoader we ultimately create.
*
* @param parent The parent class loader
*/
public WebappLoader(ClassLoader parent) {
super();
this.parentClassLoader = parent;
}
// ----------------------------------------------------- Instance Variables
/**
* The class loader being managed by this Loader component.
*/
private WebappClassLoaderBase classLoader = null;
/**
* The Context with which this Loader has been associated.
*/
private Context context = null;
/**
* The "follow standard delegation model" flag that will be used to
* configure our ClassLoader.
*/
private boolean delegate = false;
/**
* The Java class name of the ClassLoader implementation to be used.
* This class should extend WebappClassLoaderBase, otherwise, a different
* loader implementation must be used.
*/
private String loaderClass = ParallelWebappClassLoader.class.getName();
/**
* The parent class loader of the class loader we will create.
*/
private ClassLoader parentClassLoader = null;
/**
* The reloadable flag for this Loader.
*/
private boolean reloadable = false;
/**
* The string manager for this package.
*/
protected static final StringManager sm =
StringManager.getManager(Constants.Package);
/**
* The property change support for this component.
*/
protected final PropertyChangeSupport support = new PropertyChangeSupport(this);
/**
* Classpath set in the loader.
*/
private String classpath = null;
// ------------------------------------------------------------- Properties
/**
* Return the Java class loader to be used by this Container.
*/
@Override
public ClassLoader getClassLoader() {
return classLoader;
}
@Override
public Context getContext() {
return context;
}
@Override
public void setContext(Context context) {
if (this.context == context) {
return;
}
if (getState().isAvailable()) {
throw new IllegalStateException(
sm.getString("webappLoader.setContext.ise"));
}
// Deregister from the old Context (if any)
if (this.context != null) {
this.context.removePropertyChangeListener(this);
}
// Process this property change
Context oldContext = this.context;
this.context = context;
support.firePropertyChange("context", oldContext, this.context);
// Register with the new Container (if any)
if (this.context != null) {
setReloadable(this.context.getReloadable());
this.context.addPropertyChangeListener(this);
}
}
/**
* Return the "follow standard delegation model" flag used to configure
* our ClassLoader.
*/
@Override
public boolean getDelegate() {
return this.delegate;
}
/**
* Set the "follow standard delegation model" flag used to configure
* our ClassLoader.
*
* @param delegate The new flag
*/
@Override
public void setDelegate(boolean delegate) {
boolean oldDelegate = this.delegate;
this.delegate = delegate;
support.firePropertyChange("delegate", Boolean.valueOf(oldDelegate),
Boolean.valueOf(this.delegate));
}
/**
* @return the ClassLoader class name.
*/
public String getLoaderClass() {
return this.loaderClass;
}
/**
* Set the ClassLoader class name.
*
* @param loaderClass The new ClassLoader class name
*/
public void setLoaderClass(String loaderClass) {
this.loaderClass = loaderClass;
}
/**
* Return the reloadable flag for this Loader.
*/
@Override
public boolean getReloadable() {
return this.reloadable;
}
/**
* Set the reloadable flag for this Loader.
*
* @param reloadable The new reloadable flag
*/
@Override
public void setReloadable(boolean reloadable) {
// Process this property change
boolean oldReloadable = this.reloadable;
this.reloadable = reloadable;
support.firePropertyChange("reloadable",
Boolean.valueOf(oldReloadable),
Boolean.valueOf(this.reloadable));
}
// --------------------------------------------------------- Public Methods
/**
* Add a property change listener to this component.
*
* @param listener The listener to add
*/
@Override
public void addPropertyChangeListener(PropertyChangeListener listener) {
support.addPropertyChangeListener(listener);
}
/**
* Execute a periodic task, such as reloading, etc. This method will be
* invoked inside the classloading context of this container. Unexpected
* throwables will be caught and logged.
*/
@Override
public void backgroundProcess() {
if (reloadable && modified()) {
try {
Thread.currentThread().setContextClassLoader
(WebappLoader.class.getClassLoader());
if (context != null) {
context.reload();
}
} finally {
if (context != null && context.getLoader() != null) {
Thread.currentThread().setContextClassLoader
(context.getLoader().getClassLoader());
}
}
}
}
public String[] getLoaderRepositories() {
if (classLoader == null) {
return new String[0];
}
URL[] urls = classLoader.getURLs();
String[] result = new String[urls.length];
for (int i = 0; i < urls.length; i++) {
result[i] = urls[i].toExternalForm();
}
return result;
}
public String getLoaderRepositoriesString() {
String repositories[]=getLoaderRepositories();
StringBuilder sb=new StringBuilder();
for( int i=0; i<repositories.length ; i++ ) {
sb.append( repositories[i]).append(":");
}
return sb.toString();
}
/**
* Classpath, as set in org.apache.catalina.jsp_classpath context
* property
*
* @return The classpath
*/
public String getClasspath() {
return classpath;
}
/**
* Has the internal repository associated with this Loader been modified,
* such that the loaded classes should be reloaded?
*/
@Override
public boolean modified() {
return classLoader != null ? classLoader.modified() : false ;
}
/**
* Remove a property change listener from this component.
*
* @param listener The listener to remove
*/
@Override
public void removePropertyChangeListener(PropertyChangeListener listener) {
support.removePropertyChangeListener(listener);
}
/**
* Return a String representation of this component.
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder("WebappLoader[");
if (context != null)
sb.append(context.getName());
sb.append("]");
return (sb.toString());
}
/**
* Start associated {@link ClassLoader} and implement the requirements
* of {@link org.apache.catalina.util.LifecycleBase#startInternal()}.
*
* @exception LifecycleException if this component detects a fatal error
* that prevents this component from being used
*/
@Override
protected void startInternal() throws LifecycleException {
if (log.isDebugEnabled())
log.debug(sm.getString("webappLoader.starting"));
if (context.getResources() == null) {
log.info("No resources for " + context);
setState(LifecycleState.STARTING);
return;
}
// Construct a class loader based on our current repositories list
try {
classLoader = createClassLoader();
classLoader.setResources(context.getResources());
classLoader.setDelegate(this.delegate);
// Configure our repositories
setClassPath();
setPermissions();
((Lifecycle) classLoader).start();
String contextName = context.getName();
if (!contextName.startsWith("/")) {
contextName = "/" + contextName;
}
ObjectName cloname = new ObjectName(context.getDomain() + ":type=" +
classLoader.getClass().getSimpleName() + ",host=" +
context.getParent().getName() + ",context=" + contextName);
Registry.getRegistry(null, null)
.registerComponent(classLoader, cloname, null);
} catch (Throwable t) {
t = ExceptionUtils.unwrapInvocationTargetException(t);
ExceptionUtils.handleThrowable(t);
log.error( "LifecycleException ", t );
throw new LifecycleException("start: ", t);
}
setState(LifecycleState.STARTING);
}
/**
* Stop associated {@link ClassLoader} and implement the requirements
* of {@link org.apache.catalina.util.LifecycleBase#stopInternal()}.
*
* @exception LifecycleException if this component detects a fatal error
* that prevents this component from being used
*/
@Override
protected void stopInternal() throws LifecycleException {
if (log.isDebugEnabled())
log.debug(sm.getString("webappLoader.stopping"));
setState(LifecycleState.STOPPING);
// Remove context attributes as appropriate
ServletContext servletContext = context.getServletContext();
servletContext.removeAttribute(Globals.CLASS_PATH_ATTR);
// Throw away our current class loader if any
if (classLoader != null) {
try {
classLoader.stop();
} finally {
classLoader.destroy();
}
// classLoader must be non-null to have been registered
try {
String contextName = context.getName();
if (!contextName.startsWith("/")) {
contextName = "/" + contextName;
}
ObjectName cloname = new ObjectName(context.getDomain() + ":type=" +
classLoader.getClass().getSimpleName() + ",host=" +
context.getParent().getName() + ",context=" + contextName);
Registry.getRegistry(null, null).unregisterComponent(cloname);
} catch (Exception e) {
log.warn("LifecycleException ", e);
}
}
classLoader = null;
}
// ----------------------------------------- PropertyChangeListener Methods
/**
* Process property change events from our associated Context.
*
* @param event The property change event that has occurred
*/
@Override
public void propertyChange(PropertyChangeEvent event) {
// Validate the source of this event
if (!(event.getSource() instanceof Context))
return;
// Process a relevant property change
if (event.getPropertyName().equals("reloadable")) {
try {
setReloadable
( ((Boolean) event.getNewValue()).booleanValue() );
} catch (NumberFormatException e) {
log.error(sm.getString("webappLoader.reloadable",
event.getNewValue().toString()));
}
}
}
// ------------------------------------------------------- Private Methods
/**
* Create associated classLoader.
*/
private WebappClassLoaderBase createClassLoader()
throws Exception {
Class<?> clazz = Class.forName(loaderClass);
WebappClassLoaderBase classLoader = null;
if (parentClassLoader == null) {
parentClassLoader = context.getParentClassLoader();
}
Class<?>[] argTypes = { ClassLoader.class };
Object[] args = { parentClassLoader };
Constructor<?> constr = clazz.getConstructor(argTypes);
classLoader = (WebappClassLoaderBase) constr.newInstance(args);
return classLoader;
}
/**
* Configure associated class loader permissions.
*/
private void setPermissions() {
if (!Globals.IS_SECURITY_ENABLED)
return;
if (context == null)
return;
// Tell the class loader the root of the context
ServletContext servletContext = context.getServletContext();
// Assigning permissions for the work directory
File workDir =
(File) servletContext.getAttribute(ServletContext.TEMPDIR);
if (workDir != null) {
try {
String workDirPath = workDir.getCanonicalPath();
classLoader.addPermission
(new FilePermission(workDirPath, "read,write"));
classLoader.addPermission
(new FilePermission(workDirPath + File.separator + "-",
"read,write,delete"));
} catch (IOException e) {
// Ignore
}
}
for (URL url : context.getResources().getBaseUrls()) {
classLoader.addPermission(url);
}
}
/**
* Set the appropriate context attribute for our class path. This
* is required only because Jasper depends on it.
*/
private void setClassPath() {
// Validate our current state information
if (context == null)
return;
ServletContext servletContext = context.getServletContext();
if (servletContext == null)
return;
StringBuilder classpath = new StringBuilder();
// Assemble the class path information from our class loader chain
ClassLoader loader = getClassLoader();
if (delegate && loader != null) {
// Skip the webapp loader for now as delegation is enabled
loader = loader.getParent();
}
while (loader != null) {
if (!buildClassPath(classpath, loader)) {
break;
}
loader = loader.getParent();
}
if (delegate) {
// Delegation was enabled, go back and add the webapp paths
loader = getClassLoader();
if (loader != null) {
buildClassPath(classpath, loader);
}
}
this.classpath = classpath.toString();
// Store the assembled class path as a servlet context attribute
servletContext.setAttribute(Globals.CLASS_PATH_ATTR, this.classpath);
}
private boolean buildClassPath(StringBuilder classpath, ClassLoader loader) {
if (loader instanceof URLClassLoader) {
URL repositories[] = ((URLClassLoader) loader).getURLs();
for (int i = 0; i < repositories.length; i++) {
String repository = repositories[i].toString();
if (repository.startsWith("file://"))
repository = UDecoder.URLDecode(repository.substring(7));
else if (repository.startsWith("file:"))
repository = UDecoder.URLDecode(repository.substring(5));
else
continue;
if (repository == null)
continue;
if (classpath.length() > 0)
classpath.append(File.pathSeparator);
classpath.append(repository);
}
} else if (loader == ClassLoader.getSystemClassLoader()){
// Java 9 onwards. The internal class loaders no longer extend
// URLCLassLoader
String cp = System.getProperty("java.class.path");
if (cp != null && cp.length() > 0) {
if (classpath.length() > 0) {
classpath.append(File.pathSeparator);
}
classpath.append(cp);
}
return false;
} else {
log.info( "Unknown loader " + loader + " " + loader.getClass());
return false;
}
return true;
}
private static final Log log = LogFactory.getLog(WebappLoader.class);
@Override
protected String getDomainInternal() {
return context.getDomain();
}
@Override
protected String getObjectNameKeyProperties() {
StringBuilder name = new StringBuilder("type=Loader");
name.append(",host=");
name.append(context.getParent().getName());
name.append(",context=");
String contextName = context.getName();
if (!contextName.startsWith("/")) {
name.append("/");
}
name.append(contextName);
return name.toString();
}
}

View File

@@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<mbeans-descriptors>
<mbean name="WebappLoader"
description="Classloader implementation which is specialized for handling web applications"
domain="Catalina"
group="Loader"
type="org.apache.catalina.loader.WebappLoader">
<attribute name="className"
description="Fully qualified class name of the managed object"
type="java.lang.String"
writeable="false"/>
<attribute name="delegate"
description="The 'follow standard delegation model' flag that will be used to configure our ClassLoader"
type="boolean"/>
<attribute name="reloadable"
description="The reloadable flag for this Loader"
type="boolean"/>
<attribute name="stateName"
description="The name of the LifecycleState that this component is currently in"
type="java.lang.String"
writeable="false"/>
<attribute name="loaderRepositories"
description="Repositories set in the real loader"
type="[Ljava.lang.String;"
writeable="false" />
<attribute name="loaderRepositoriesString"
description="Repositories set in the real loader"
type="java.lang.String"
writeable="false" />
<operation name="toString"
description="Info about the loader"
impact="INFO"
returnType="String">
</operation>
</mbean>
<mbean name="WebappClassLoader"
description="Classloader implementation which is specialized for handling web applications"
domain="Catalina"
group="Loader"
type="org.apache.catalina.loader.WebappClassLoader">
<attribute name="className"
description="Fully qualified class name of the managed object"
type="java.lang.String"
writeable="false"/>
<attribute name="contextName"
description="Name of the webapp context"
type="java.lang.String"
writeable="false"/>
<attribute name="delegate"
description="The 'follow standard delegation model' flag that will be used to configure our ClassLoader"
type="boolean"/>
<attribute name="stateName"
description="The name of the LifecycleState that this component is currently in"
type="java.lang.String"
writeable="false"/>
<attribute name="URLs"
description="The URLs of this loader"
type="[Ljava.net.URL;"/>
</mbean>
<mbean name="ParallelWebappClassLoader"
description="Classloader implementation which is specialized for handling web applications and is capable of loading classes in parallel"
domain="Catalina"
group="Loader"
type="org.apache.catalina.loader.ParallelWebappClassLoader">
<attribute name="className"
description="Fully qualified class name of the managed object"
type="java.lang.String"
writeable="false"/>
<attribute name="contextName"
description="Name of the webapp context"
type="java.lang.String"
writeable="false"/>
<attribute name="delegate"
description="The 'follow standard delegation model' flag that will be used to configure our ClassLoader"
type="boolean"/>
<attribute name="stateName"
description="The name of the LifecycleState that this component is currently in"
type="java.lang.String"
writeable="false"/>
<attribute name="URLs"
description="The URLs of this loader"
type="[Ljava.net.URL;"/>
</mbean>
</mbeans-descriptors>