Friday, October 30, 2009

java.lang.NoSuchMethodError: org.objectweb.asm.ClassVisitor

Certa ocasião enfrentei o problema abaixo em uma aplicação web desenvolvida em Java 1.5 executando em WebSphere 6.1.

Vou postar o problema, a análise e a solução.

O stack trace gerado é o seguinte:

[9/17/09 5:15:10:196 BRT] 0000001e WebGroup A SRVE0169I: Loading Web Module: VC.war.
[9/17/09 5:15:17:163 BRT] 0000001e WebApp A SRVE0180I: [VC#VC.war] [/appsl/vc] [Servlet.LOG]: Initializing We
bApplicationContext for Struts ActionServlet 'action', module ''
[9/17/09 5:15:34:344 BRT] 0000001e ContextLoader E org.springframework.web.struts.ContextLoaderPlugIn init Context initialization failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in ServletContext resource [/WEB-INF/classes/com/citi/vc/config/spring/spring-daos-config.xml]: Invocation of init method failed; nested exception is java.lang.NoSuchMethodError: org.objectweb.asm.ClassVisitor.visit(IILjava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)V
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowir

eCapableBeanFactory.java:1336)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireC
apableBeanFactory.java:471)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
at java.security.AccessController.doPrivileged(Native Method)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:220)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:423)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:729)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:381)
at org.springframework.web.struts.ContextLoaderPlugIn.createWebApplicationContext(ContextLoaderPlugIn.java:354)
at org.springframework.web.struts.ContextLoaderPlugIn.initWebApplicationContext(ContextLoaderPlugIn.java:295)
at org.springframework.web.struts.ContextLoaderPlugIn.init(ContextLoaderPlugIn.java:225)
at org.apache.struts.action.ActionServlet.initModulePlugIns(ActionServlet.java:869)
at org.apache.struts.action.ActionServlet.init(ActionServlet.java:336)
at javax.servlet.GenericServlet.init(GenericServlet.java:256)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.init(ServletWrapper.java:227)
at com.ibm.ws.wswebcontainer.servlet.ServletWrapper.init(ServletWrapper.java:320)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.initialize(ServletWrapper.java:1308)
at com.ibm.ws.wswebcontainer.servlet.ServletWrapper.initialize(ServletWrapper.java:153)
at com.ibm.wsspi.webcontainer.extension.WebExtensionProcessor.createServletWrapper(WebExtensionProcessor.java:99)
at com.ibm.ws.webcontainer.webapp.WebApp.getServletWrapper(WebApp.java:897)
at com.ibm.ws.webcontainer.webapp.WebApp.getServletWrapper(WebApp.java:819)
at com.ibm.ws.webcontainer.webapp.WebApp.initializeTargetMappings(WebApp.java:537)
at com.ibm.ws.webcontainer.webapp.WebApp.commonInitializationFinish(WebApp.java:374)
at com.ibm.ws.wswebcontainer.webapp.WebApp.initialize(WebApp.java:293)
at com.ibm.ws.wswebcontainer.webapp.WebGroup.addWebApplication(WebGroup.java:93)
at com.ibm.ws.wswebcontainer.VirtualHost.addWebApplication(VirtualHost.java:162)
at com.ibm.ws.wswebcontainer.WebContainer.addWebApp(WebContainer.java:671)
at com.ibm.ws.wswebcontainer.WebContainer.addWebApplication(WebContainer.java:624)
at com.ibm.ws.webcontainer.component.WebContainerImpl.install(WebContainerImpl.java:335)
at com.ibm.ws.webcontainer.component.WebContainerImpl.start(WebContainerImpl.java:551)
at com.ibm.ws.runtime.component.ApplicationMgrImpl.start(ApplicationMgrImpl.java:1274)
at com.ibm.ws.runtime.component.DeployedApplicationImpl.fireDeployedObjectStart(DeployedApplicationImpl.java:1165)
at com.ibm.ws.runtime.component.DeployedModuleImpl.start(DeployedModuleImpl.java:569)
at com.ibm.ws.runtime.component.DeployedApplicationImpl.start(DeployedApplicationImpl.java:832)
at com.ibm.ws.runtime.component.ApplicationMgrImpl.startApplication(ApplicationMgrImpl.java:921)
at com.ibm.ws.runtime.component.ApplicationMgrImpl$AppInitializer.run(ApplicationMgrImpl.java:2124)
at com.ibm.wsspi.runtime.component.WsComponentImpl$_AsynchInitializer.run(WsComponentImpl.java:342)
at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1497)
Caused by: java.lang.NoSuchMethodError: org.objectweb.asm.ClassVisitor.visit(IILjava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)V
at net.sf.cglib.core.ClassEmitter.begin_class(ClassEmitter.java:77)
at net.sf.cglib.core.KeyFactory$Generator.generateClass(KeyFactory.java:173)
at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)
at net.sf.cglib.core.KeyFactory$Generator.create(KeyFactory.java:145)
at net.sf.cglib.core.KeyFactory.create(KeyFactory.java:117)
at net.sf.cglib.core.KeyFactory.create(KeyFactory.java:108)
at net.sf.cglib.core.KeyFactory.create(KeyFactory.java:104)
at net.sf.cglib.proxy.Enhancer.(Enhancer.java:69)
at org.hibernate.proxy.pojo.cglib.CGLIBLazyInitializer.getProxyFactory(CGLIBLazyInitializer.java:117)
at org.hibernate.proxy.pojo.cglib.CGLIBProxyFactory.postInstantiate(CGLIBProxyFactory.java:43)
at org.hibernate.tuple.entity.PojoEntityTuplizer.buildProxyFactory(PojoEntityTuplizer.java:162)
at org.hibernate.tuple.entity.AbstractEntityTuplizer.(AbstractEntityTuplizer.java:135)
at org.hibernate.tuple.entity.PojoEntityTuplizer.(PojoEntityTuplizer.java:55)
at org.hibernate.tuple.entity.EntityEntityModeToTuplizerMapping.(EntityEntityModeToTuplizerMapping.java:56)
at org.hibernate.tuple.entity.EntityMetamodel.(EntityMetamodel.java:295)
at org.hibernate.persister.entity.AbstractEntityPersister.(AbstractEntityPersister.java:434)
at org.hibernate.persister.entity.SingleTableEntityPersister.(SingleTableEntityPersister.java:109)
at org.hibernate.persister.PersisterFactory.createClassPersister(PersisterFactory.java:55)
at org.hibernate.impl.SessionFactoryImpl.(SessionFactoryImpl.java:226)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1294)
at org.springframework.orm.hibernate3.LocalSessionFactoryBean.newSessionFactory(LocalSessionFactoryBean.java:814)
at org.springframework.orm.hibernate3.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:732)
at org.springframework.orm.hibernate3.AbstractSessionFactoryBean.afterPropertiesSet(AbstractSessionFactoryBean.java:211)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1367)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1333)
... 42 more

2 comments:

Luciano de Carvalho Rodrigues said...

A Análise:

Após receber a informação de que a classe ClasVisitor da lib asm.jar, pretence a lib cglib (cglib 2.1_3 do Spring (AOP)) que foi incorporada no sistema no dia 4 de junho de 2009.

Questionamos se existiu alguma mudança nessa lib recentemente. Co a respostas negativa analisei mais a fundo as situações abaixo:


Análise 1 – Comparação libs Ambiente de Instalação Cliente vs Fábrica de Software

Fiz a análise entre as versões de API do ambiente Ambiente de Instalação Cliente e da Fábrica e não encontrei problema algum.

Esta análise já havia sido feita entra a fábrica e CTI em 03/06/2009, conforme arquivo VC_libs.xls, que mostra esta comparação.

Nesta ocasião chegamos a conclusão que deveria ser incluída o arquivo cglib-nodep-2.1_3.



Conclusão: não é a origem do problema.



Análise 2 – Comparação entre versões do asm.jar que estão no VC.

Há no VC.ear 2 jars asm.jar: um proveniente do cglib-nodep-2.1_3 e outro do hibernate-3.2.4.sp1

Comparando-os as classes ClassVisitor verifiquei que eles tem a mesma assinatura:

public abstract void visit(int i, int j, String s, String s1, String as[], String s2);



Portanto não haveria conflito. E de toda forma os pacotes são diferentes

cglib-nodep-2.1_3

asm.jar

net.sf.cglib.asm.ClassVisitor

public abstract void visit(int i, int j, String s, String s1, String as[], String s2);

hibernate-3.2.4.sp1

asm.jar

org.objectweb.asm.ClassVisitor

public abstract void visit(int i, int j, String s, String s1, String as[], String s2);



Conclusão: não é a origem do problema, pois não há conflito entre os jars.



Análise 3 – Conflito entre o VC e outras aplicações da JVM

A partir deste ponto passei a acreditar que o problema não estava apenas nas libs da aplicação, mas que havia um conflito entre as aplicações que estão rodando na mesma JVM.

A classe que temos conflito é a org.objectweb.asm.ClassVisitor, que está na library 100 - Spring Framework (CGLIB NODEP), do B&D.



Também existe no mesmo ambiente a library do B&D existe também a library 53 – Spring Framework (v.1.1.5).

Esta versão do Spring tem dependência com a versão do asm-2.2.3, onde a ClassVisitor tem a assinatura abaixo:

public abstract void visit(int i, int j, String s, String s1, String s2, String as[]);



Esta assinatura é diferente da que utilizamos: public abstract void visit(int i, int j, String s, String s1, String as[], String s2);



Se a JVM carregar esta classe e o VC tentar utilizá-la não encontrará o método ClassVisitor.visit com a assinatura necessária. Gerando um erro NoSuchMethodError.



Conclusão: pode ser que uma versão incorreta da ClassVisitor está em uso na mesma JVM. Problema de classloader.

Podemos testar esta conclusão carregaando o VC em uma JVM independente.



Solução: será necessário encontrar alguma forma para que as aplicações que usem APIs de versão diferentes não tenham conflito devido ao classloader.

Já tivemos este problema anteriormente com o Hibernate 3.0 e o 3.2 e a solução foi rodar em outra JVM, veja e-mail

Luciano de Carvalho Rodrigues said...

A Solução:
No Forum SpringSource há um post sobre o assunto neste link http://forum.springsource.org/showthread.php?t=10617

Mas isto não respondia o problema, pois se a JVM carregar esta classe e o VC tentar utilizá-la não encontrará o método ClassVisitor.visit com a assinatura necessária. Gerando um erro NoSuchMethodError.

Ajustei novamente o script de compilação para passar a usar a biblioteca cglib sem dependencias.