31
JBoss Class Loader Overview do modelo de Class Loader no JBoss AS

JBossClassLoader

Embed Size (px)

DESCRIPTION

Breve introdução ao modelo de class loader do JBoss AS.

Citation preview

Page 1: JBossClassLoader

JBoss Class LoaderOverview do modelo de Class Loader no JBoss AS

Page 2: JBossClassLoader

Java Class Loader

•Tipo x Classe▫Class Type: Nome totalmente qualificado

da classe Ex: com.mycompany.MyClass

▫Class: formado pelo class type e pelo class loader responsável por carregar (byte code) e definir o tipo. Enfim uma instância de java.lang.class – byte

code carregado JavaDoc: "Every Class object contains a

reference to the ClassLoader that defined it."

2

® Rafael Torres 2008

Page 3: JBossClassLoader

Java Class Loader• Regra geral segundo o JavaDoc da API: Sempre que

uma classe/recurso for requisita, uma instância de Class Loader irá delegar a busca primeiro para o Class Loader pai. Somente se o pai não puder carregar a classe, a instância do class loader em questão deve carregar.

• Exceção a regra: em alguns casos é necessário reduzir o escopo de uma determinada classe/recurso. Neste caso o próprio class loader solicitado carrega a classe. ▫ Este é o caso dos servlet containers e dos EJB

containers.▫ Nesta situação um class loader pode ter apenas uma

única representação de um tipo carregada. Isso significa, por exemplo, que você só pode ter um único class type com.mycompany.MyClass em um mesmo class loader.

3

® Rafael Torres 2008

Page 4: JBossClassLoader

Java Class Loader

•Para mais detalhes sobre o funcionamento e modelo do Class Loader Java consulte:▫Dynamic Class Loading in the Java™ virtual

Machine: http://www.cs.purdue.edu/homes/jv/smc/pubs/liang-oopsla98.pdf (Esse é das raízes mesmo... )

▫Understanding the Java Classloading Mechanism http://java.sys-con.com/node/37659/print

4

® Rafael Torres 2008

Page 5: JBossClassLoader

Class loader no JBoss AS Unifield Class Loader

• O Componente central deste modelo é o: org.jboss.mx.loading.UnifiedClassLoader3 (UCL)▫ Esse cara estende a classe java.net.URLClassLoader do Java

e sobrescreve o comportamento padrão do modelo "parent delegation" : JavaDoc API: "The ClassLoader class uses a delegation

model to search for classes and resources. Each instance of ClassLoader has an associated parent class loader"

▫ Usa um repositório compartilhado de classes e recursos: org.jboss.mx.loading.UnifiedLoaderRepository3 (ULR)

▫ Neste modelo cada UCL é associado à um único UnifieldLoaderRepository3, e um ULR por sua vez tem vários UCLs associados.

▫ Um UCL pode ter várias URLs (endereços de classes/jars/libs) associadas a ele para o carregamento (loading) de classes e recursos.

5

® Rafael Torres 2008

Page 6: JBossClassLoader

Unifield Class loader• Deployers usam o UCL de nível mais alto como

um class loader compartilhado e então todos os pacotes de deploy (WAR, SAR, EAR, HAR, etc) são associados a este class loader.

• Quando um UCL é solicitado para carregar uma classe ele:▫ Verifica no repositório

(UnifieldLoaderRepository3) com o qual ele está associado se a classe já foi carregada.

▫ O UCL carregará a classe apenas se ela ainda não existir no repositório.

• Por padrão existe apenas 1 repositório (ULR) compartilhado para todas as instâncias de UCLs.▫ Isto significa que as instâncias de UCLs formam um

único espaço de nomes para o class loader.

6

® Rafael Torres 2008

Page 7: JBossClassLoader

Esquema de Class Loader no JBoss AS•Veja o diagrama não muito didático...

Jboss AS Guide – ch 2 [1]

7

® Rafael Torres 2008

Page 8: JBossClassLoader

Sequência de carregamento de classes e recursos• A seguinte seqüência de passos ocorre quando o método

UnfiedClassLoader3.loadClass(String, boolean) é invocado:

1. Verifica se a classe já foi carregada antes

Cache: contém classe que já foram carregadas por uma instância do UCL

abc.classxyz.classArq.properties...

URLs: locais onde as classes, pacotes estão armazenados: direório deploy, lib, etc

2. Procura a classe nos URLClassLoaders ou se está visível em um class loader pai.

2.1 Se a classe foi encontra, é colocada no cache (ULR) e retornada para uso...

Jboss AS Guide – ch 2 [1]

2.2 próximo slide...

8

® Rafael Torres 2008

Page 9: JBossClassLoader

Sequência de carregamento de classes e recursos...• "2.2 Caso contrário – a classe não foi encontrada nas

URLs associadas aos UCLs – O repositório cache (ULR) é consultado para todos os UCLs que sejam capazes de fornecer a classe com base no mapeamento de nome de pacotes/UCL.

• Quando um UCL é adicionado (associado) ao repositório cache (repositório ULR3 – que é único) é estabelecida uma associação entre os nomes de pacotes disponíveis nas URLs associadas ao UCL em questão.

• Isso permite determinar qual UCL é capaz de carregar uma determinada classe.

• Os UCLs são consultados sobre a classe requisitada na ordem em que os UCLs foram adicionados ao repositório (ULR3).

• Nesta busca, se algum UCL for capaz de carregar a classe, ela é retornada, caso contrário um

• java.lang.ClassNotFoundException é lançado." [1]

9

® Rafael Torres 2008

Jboss AS Guide – ch 2 [1]

Page 10: JBossClassLoader

Class loading no JBoss AS...

10

® Rafael Torres 2008

JBossClassLoadingUseCases (wiki.jboss.org) [2]

Page 11: JBossClassLoader

Descrição mais detalhada: wiki.jboss.org...•JBossClassLoadingUseCases:

▫https://www.jboss.org/community/docs/DOC-10290

11

® Rafael Torres 2008

Page 12: JBossClassLoader

Aplicações WEB® Rafael Torres

2008

12

• Java™ Servlet Specification Version 2.3

Page 13: JBossClassLoader

Visibilidade entre class loaders no AS

13

® Rafael Torres 2008

JBoss in Action – Figura 3.3 [4]

Page 14: JBossClassLoader

Visibilidade entre class loaders no AS• No diagrama anterior classes de um certo nível possuem acesso/visibilidade à classes

do mesmo nível ou de um nível mais baixo, mas não o contrário.• Para alterar este comportamento padrão (definido na Servltet spec 2.3) os seguintes

atributos devem ser alterados:

<!-- Get the flag indicating if the normal Java2 parent first class

loading model should be used over the servlet 2.3 web container first

model.

-->

<attribute name="Java2ClassLoadingCompliance">false</attribute>

<!-- A flag indicating if the JBoss Loader should be used. This loader

uses a unified class loader as the class loader rather than the tomcat

specific class loader.

The default is false to ensure that wars have isolated class loading

for duplicate jars and jsp files.

-->

<attribute name="UseJBossWebLoader">false</attribute>

• O arquivo com essa config está em JBOSS_HOME/server/MyConfig/deploy/jboss-web.deployer/META-INF/jboss-service.xml

• ATENÇÃO: está alteração pode causar efeitos colaterais indesejáveis. Não haverá isolamento de class loader – suas classes ficarão visíveis como se estivesse em um único espaço compartilhado.

14

® Rafael Torres 2008

Page 15: JBossClassLoader

java2ParentDelegation•O default é true para aplicações JEE.

Exceto para WEB Apps (Servlet spec. 2.3)• java2ParentDelegation=false

▫Força o JBoss usar a versão da classe localizada dentro do repositório isolado da APP (EAR, SAR, WAR, etc) – se houver mais de uma versão de classe carregada no repositório.

▫Se a classe não puder ser carregada pelo UCL da APP, o JBoss busca em seu próprio UCL (server/xxx/lib, JBOSS_HOME/lib, etc).

15

® Rafael Torres 2008

Page 16: JBossClassLoader

Níveis de class loader•No nível mais baixo estão as classes do

classpath da JVM (rt.jar, tools.jar, etc) e as classes usadas na inicialização do AS encontradas no diretório JBOSS_HOME/lib.

•O próximo nível contém classes compartilhadas para as aplicações deployadas no AS em JBOSS_HOME/server/<server-config>/deploy e as bibliotecas disponíveis em JBOSS_HOME/server/<server-config>/lib.

•O nível mais alto representa classes contidas em um arquivo WAR, o qual pode estar contido dentro do diretório deploy ou dentro de um pacote EAR ou SAR.

16

® Rafael Torres 2008

Page 17: JBossClassLoader

Classes/Bibliotecas compartilhadas• O esquema de class loader compartilhado no AS é

conveniente quando se deseja compartilhar suas bibliotecas de classes com todas as aplicações.

• Se suas aplicações não puderem compartilhar bibliotecas de classes para evitar conflito entre versões, você precisará isolar o class loader da aplicação.

• Sem isolamento de class loader alguns problemas podem ser encontrados: ▫ ClassCastException, ▫ IllegalAccessErrors, ▫ VerifyErrors e ▫ Alguns comportamentos estranhos durantes novos

deploys/redeploys/undeploy. • Para isso é necessário utilizar o mecanismo de escopo

de classes.

17

® Rafael Torres 2008

Page 18: JBossClassLoader

J2ee Specification•J2EE 1.4 Specification

▫"There must be only one version of each class in an application."

▫ "All components in a single application may be loaded in a single class loader and share a single namespace. "

18

® Rafael Torres 2008

Page 19: JBossClassLoader

Scoping class•Neste esquema você pode definir um class

loader repository específico para sua APP – um repositório isolado. ▫HierarchicalClassLoader3

•É possível fazer isso definindo um class loader repository em um arquivo de configuração descritor específico para o JBoss AS.

19

® Rafael Torres 2008

Page 20: JBossClassLoader

Scoping classes• Em um arquivo SAR (META-INF/jboss-service.xml):

• Em um arquivo EAR (META-INF/jboss-app.xml):

• Em um arquivo WAR(WEB-INF/jboss-web.xml):

<service><loader-repository>jbia.loader:loader=Loader1</loader-repository>. . .</service>

<jboss-app><loader-repository>jbia.loader:loader=Loader2</loader-repository>. . .</jboss-app>

<jboss-web><class-loading><loader-repository>jbia.loader:loader=Loader3</loader-repository></class-loading>. . .</jboss-web>

20

® Rafael Torres 2008

Page 21: JBossClassLoader

Escopo de classes – HierarchicalLoaderRepository3

• Visualizando o Class Loader isolado de uma Aplicação no JMX Console do JBoss.

21

® Rafael Torres 2008

Page 22: JBossClassLoader

Alguns testes...• Cenário 1:

▫ com.mycompany.mylibs.ClassA v1 (lib.jar) em App1.ear ▫ com.mycompany.mylibs.ClassA v2 (lib.jar) em

server/default/lib▫ displayClassInfo() JMX Mbean Operation:

com.mycompany.mylibs.ClassA Information Not loaded in repository cache

### Instance0 found in UCL: org.jboss.mx.loading.UnifiedClassLoader3@18a49e0{ url=null ,addedOrder=2}

### Instance1 found in UCL: org.jboss.mx.loading.UnifiedClassLoader3@e8709d{ url=file:/C:/java/tools/jbdevstudio/jboss-eap/jboss-as/server/default/deploy/App1.ear/ ,addedOrder=38} • De qual UCL a classe será retornada?

▫ Observe a ordem em que o UCL foi associado ao repositório...

17:38:09,934 INFO [STDOUT] Eu sou a versao 2 da classe A17:38:09,934 INFO [STDOUT] logA(): ContextClassLoader - org.jboss.mx.loading.UnifiedClassLoader3@e8709d{ url=file:/C:/java/tools/jbdevstudio/jboss-eap/jboss-as/server/default/deploy/App1.ear/ ,addedOrder=38}

22

® Rafael Torres 2008

A classe foi requisitada para o UCL do EAR (addedOrder=38), mas quem retornou foi o UCL associado à URL server/default/lib (addedOrder=2)!

Page 23: JBossClassLoader

Alguns testes...• Cenário 2:

▫ com.mycompany.mylibs.ClassA v1 (lib.jar) em APP1.ear ▫ com.mycompany.mylibs.ClassA v2 (lib.jar) em server/default/lib▫ Escopo de classe declarado

com.mycompany.mylibs.ClassA Information Not loaded in repository cache

### Instance 0 found in UCL: org.jboss.mx.loading.UnifiedClassLoader3@16d2633{ url=null ,addedOrder=2}• De qual UCL a classe será retornada?

▫ Observe a ordem em que o UCL foi associado ao repositório...10:42:23,635 INFO [STDOUT] logA(): Eu sou a versao 1 da classe A10:42:23,636 INFO [STDOUT] logA(): ContextClassLoader - org.jboss.mx.loading.UnifiedClassLoader3@557d7e{ url=file:/C:/java/tools/jbdevstudio/jboss-eap/jboss-as/server/default/deploy/App1.ear/ ,addedOrder=36}

▫displayClassInfo() JMX Mbean Operation:

<jboss-app><loader-repository> EJBTest.loader:loader=Loader1</loader-repository>

</jboss-app>

23

® Rafael Torres 2008

Observe que agora a classe aparece apenas no UCL do AS, pois foi encontrada em server/xxx/lib.

Page 24: JBossClassLoader

Alguns testes...• Cenário 3:

▫ com.mycompany.mylibs.ClassA v1 (lib.jar) removido de APP1.ear▫ com.mycompany.mylibs.ClassA v2 (lib.jar) em server/default/lib▫ Escopo de classe declarado▫ java2ParentDelegation desligado!

com.mycompany.mylibs.ClassA Information Not loaded in repository cache

### Instance 0 found in UCL: org.jboss.mx.loading.UnifiedClassLoader3@16d2633{ url=null ,addedOrder=2}• De qual UCL a classe será retornada?

▫ Observe a ordem em que o UCL foi associado ao repositório...10:58:49,844 INFO [STDOUT] Eu sou a versao 2 da classe A10:58:49,844 INFO [STDOUT] logA(): ContextClassLoader - org.jboss.mx.loading.UnifiedClassLoader3@348ab2{ url=file:/C:/java/tools/jbdevstudio/jboss-eap/jboss-as/server/default/deploy/App1.ear/ ,addedOrder=36}

▫ displayClassInfo() JMX Mbean Operation:

<jboss-app><loader-repository> EJBTest.loader:loader=Loader1

<loader-repository-config>java2ParentDelegation=false</loader-repository-config>

</loader-repository></jboss-app>

24

® Rafael Torres 2008

No Loader1 (escopo de classe) a classe A não foi carregada! Foi removida de dentro do EAR.O objetivo é verificar se o JBoss encontrará a classe no UCL pai (do AS: server/xxx/lib).

Page 25: JBossClassLoader

Alguns testes...• Cenário 4:

▫ 2 EARs (App1 e APP2)▫ com.mycompany.mylibs.ClassA v1 (lib.jar) removido de App1.ear ▫ App1.ear com escopo de classe!▫ com.mycompany.mylibs.ClassA v2 (lib.jar) em App2.ear▫ App2.ear sem escopo de classe.▫ displayClassInfo() JMX Mbean Operation :

com.mycompany.mylibs.ClassA Information Not loaded in repository cache

• De qual UCL a classe será retornada?▫ Observe a ordem em que o UCL foi associado ao repositório...

13:13:41,961 INFO [STDOUT] logA(): Eu sou a versao 1 da classe A13:13:41,962 INFO [STDOUT] logA(): ContextClassLoader - org.jboss.mx.loading.UnifiedClassLoader3@6196fc{ url=file:/C:/java/tools/jbdevstudio/jboss-eap/jboss-as/server/default/deploy/App1.ear/ ,addedOrder=36}

▫ antes de invocar o EJB de APP1.ear :

com.mycompany.mylibs.ClassA Information Repository cache version: com.mycompany.mylibs.ClassA(1bb6976).ClassLoader=org.jboss.mx.loading.UnifiedClassLoader3@efae3b{ url=file:/C:/java/tools/jbdevstudio/jboss-eap/jboss-as/server/default/deploy/App2.ear/ ,addedOrder=37}

▫ depois de invocar o EJB de APP1.ear :

25

® Rafael Torres 2008

Neste cenário apenas App2.ear contem a ClasseA v2.Chamaremos o EJB de App1 que não possui/carrega ClasseA.

O UCL solicitado foi o de App1.ear, porém que retornou ClasseA foi o UCL de App2.ear

Podemos concluir com isso que mesmo empacotando duas APPs em EAR separados as classes são compartilhadas em um mesmo espaço no AS. A menos que se isole o ClassLoader das duas Apps. Nesse caso este último teste retornaria ClassNotfoundException.

Page 26: JBossClassLoader

Alguns testes...• Cenário 5 - o mais complexo

▫ 2 EARs (App1 e APP2) ambos com EJBs Statless Session Bean

▫ Interface remota/local em EJBTestClient.jar: sever/default/deploy/EJBTestClient.jar - class loader

compartilhado...▫ com.mycompany.mylibs.ClassA (lib.jar) no class path do

EAR: App1.ear/lib/lib.jar App2.ear/lib/lib.jar

▫ Ambos com escopo de classe duas opções:

alterar ear-deployer.xml: atrbuto Isolated true definir o class loader em jboss-app.xml como visto anteriormente

▫ Dois comportamentos distintos e estranhos Chamada remota (call-by-value) com o ônus da serialização Chamada local (call-by-reference) na mesma JVM

26

® Rafael Torres 2008

Page 27: JBossClassLoader

Call-by-value X Call-by-reference no JBoss

• Naming Service: server/default/conf/jboss-service.xml

... <mbean code="org.jboss.naming.NamingService" name="jboss:service=Naming" xmbean-dd="resource:xmdesc/NamingService-xmbean.xml"> <!-- The call by value mode. true if all lookups are unmarshalled using the caller's TCL, false if in VM lookups return the value by reference. --> <attribute name="CallByValue">false</attribute>

• EAR Deployer Service: server/default/deploy/ear-deployer.xml

<!-- EAR deployer, remove if you are not using ear deployments --> <mbean code="org.jboss.deployment.EARDeployer" name="jboss.j2ee:service=EARDeployer"> <!-- A flag indicating if ear deployments should have their own scoped class loader to isolate their classes from other deployments. --> <attribute name="Isolated">false</attribute> <!-- A flag indicating if the ear components should have in VM call optimization disabled. --> <attribute name="CallByValue">false</attribute>

27

® Rafael Torres 2008

Page 28: JBossClassLoader

No JBoss...•Cenário 5 com a configuração padrão do

JBoss: ▫Chamada remota

ERROR [STDERR] java.lang.ClassCastException: $Proxy65...

O JBoss tenta otimizar os lookups feitos dentro da mesma VM: call-by-reference Workaround:

▫alterar Call-By-Value true em Naming Service (conf/jboss-service.xml)

▫Isso faz com que todo lookup seja serializado (call-by-value)

Após alteração: Tudo funciona!

28

® Rafael Torres 2008

Page 29: JBossClassLoader

No JBoss...29

® Rafael Torres 2008

Page 30: JBossClassLoader

Leitura recomendada:• Dynamic Class Loading in the Java™ virtual Machine

▫ http://www.cs.purdue.edu/homes/jv/smc/pubs/liang-oopsla98.pdf • Understanding the Java Classloading Mechanism

▫ http://java.sys-con.com/node/37659/print• Java SE 6 API

▫ http://java.sun.com/javase/6/docs/api/java/lang/ClassLoader.html• Classloading e o porquê você deveria ao menos saber como isso

funciona▫ http://nullability.org/?p=95

• Classloader hell▫ http://www.kumpera.net/blog/index.php/2007/05/09/classloader-hell/

• JBossClassLoadingUseCases:▫ https://www.jboss.org/community/docs/DOC-10290

• ClassLoadingConfiguration▫ http://www.jboss.org/community/docs/DOC-9288

• Class loaders e aplicações isoladas no JBoss▫ http://www.mouseoverstudio.com/blog/2008/06/24/classloaders-e-aplicacoes-

isoladas-no-jboss/

® Rafael Torres 2008

30

Page 31: JBossClassLoader

Referências• [1]

http://docs.jboss.org/jbossas/jboss4guide/r4/html/ch2.chapter.html#ch2.loadarch.fig

• [2] JBossClassLoadingUseCases https://www.jboss.org/community/docs/DOC-10290

• [3] JMAE Javide, PETER Johnson. JBoss in Action. 2008 Manning. pag. 53

• [4] http://www.middleware.vt.edu/doku.php?id=middleware:jboss:classloading

31

® Rafael Torres 2008