本文共 20629 字,大约阅读时间需要 68 分钟。
前段时间一直在做应用容器的迁移,将公司的应用容器从jboss,tomcat统一迁移到jetty。在整个迁移过程中遇到最多的潜在问题还是在classloader机制上,这里记录一下希望能对大家有所帮助,避免重复走弯路。
啥都不说,先来看下遇到的几个问题,比较纠结的问题。
1.Caused by: java.lang.SecurityException: sealing violation: package com.sun.media.jai.util is sealed 2. at java.net.URLClassLoader.defineClass(URLClassLoader.java:234) 3. at java.net.URLClassLoader.access$000(URLClassLoader.java:58) 4. at java.net.URLClassLoader$1.run(URLClassLoader.java:197) 5. at java.security.AccessController.doPrivileged(Native Method) 6. at java.net.URLClassLoader.findClass(URLClassLoader.java:190) 7. at org.eclipse.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:419) 8. at org.eclipse.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:381) 9. at java.lang.ClassLoader.defineClass1(Native Method) 10. at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632)
1.Caused by: java.lang.NoSuchMethodError: javax.xml.parsers.SAXParserFactory.newInstance(Ljava/lang/String;Ljava/lang/ClassLoader;)Ljavax/xml/parsers/SAXParserFactory;
1.java.lang.reflect.InvocationTargetException 2. at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 3. at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 4. at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 5. at java.lang.reflect.Method.invoke(Method.java:597) 6. at org.eclipse.jetty.start.Main.invokeMain(Main.java:490) 7. at org.eclipse.jetty.start.Main.start(Main.java:634) 8. at org.eclipse.jetty.start.Main.parseCommandLine(Main.java:280) 9. at org.eclipse.jetty.start.Main.main(Main.java:82) 10.Caused by: javax.xml.parsers.FactoryConfigurationError: Provider org.apache.xerces.jaxp.SAXParserFactoryImpl not found 11. at javax.xml.parsers.SAXParserFactory.newInstance(SAXParserFactory.java:134) 12. at org.eclipse.jetty.xml.XmlParser.(XmlParser.java:68) 13. at org.eclipse.jetty.xml.XmlConfiguration.initParser(XmlConfiguration.java:79) 14. at org.eclipse.jetty.xml.XmlConfiguration. (XmlConfiguration.java:112) 15. at org.eclipse.jetty.xml.XmlConfiguration$1.run(XmlConfiguration.java:1028) 16. at java.security.AccessController.doPrivileged(Native Method) 17. at org.eclipse.jetty.xml.XmlConfiguration.main(XmlConfiguration.java:983) 18. ... 8 more
1.Djavax.xml.parsers.SAXParserFactory=org.apache.xerces.jaxp.SAXParserFactoryImpl
1.Caused by: java.lang.ClassNotFoundException: javax.mail.event.TransportListener 2. at java.net.URLClassLoader$1.run(URLClassLoader.java:202) 3. at java.security.AccessController.doPrivileged(Native Method) 4. at java.net.URLClassLoader.findClass(URLClassLoader.java:190) 5. at org.eclipse.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:419) 6. at org.eclipse.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:381) 7. ... 78 more
可以说基本都是对应的class , method等找不到,或者类冲突等问题,一看就是比较典型的classloader引发的问题。
这里早期对jboss classloader几点配置做了下说明,可以参见: http://agapple.iteye.com/blog/791940
为了和tomcat,jetty有更明显的对比,这里就主要介绍三个参数代码层面上的实现:
1.2. 3. 4. 6....... 7. 8. 12. false 13. 19.true 20. 28.javax.servlet,org.apache.commons.logging 29. 30...... 31. 32.
相信这几个参数大家都应该比较熟知,配置项在 deploy/jbossweb-tomcat55.sar/META-INF/jboss-service.xml中
下面循着代码来看一下jboss的相关实现:
1.if (ctxPath.equals("/") || ctxPath.equals("/ROOT") || ctxPath.equals("")) 2. { 3. log.debug("deploy root context=" + ctxPath); 4. ctxPath = "/"; 5. metaData.setContextRoot(ctxPath); 6. } 7. 8. URL url = new URL(warUrl); 9. 10. ClassLoader loader = Thread.currentThread().getContextClassLoader(); 11. /* If we are using the jboss class loader we need to augment its path 12. to include the WEB-INF/{lib,classes} dirs or else scoped class loading 13. does not see the war level overrides. The call to setWarURL adds these 14. paths to the deployment UCL. 15. */ 16. Loader webLoader = null; 17. if (config.isUseJBossWebLoader()) // 这里对useJbossWebLoader进行判断,进行不同的classloader处理 18. { 19. WebCtxLoader jbossLoader = new WebCtxLoader(loader); 20. jbossLoader.setWarURL(url); 21. webLoader = jbossLoader; 22. } 23. else 24. { 25. String[] pkgs = config.getFilteredPackages(); 26. WebAppLoader jbossLoader = new WebAppLoader(loader, pkgs); 27. jbossLoader.setDelegate(getJava2ClassLoadingCompliance()); 28. webLoader = jbossLoader; 29. }
1.if (webLoader != null) 2. { 3. server.setAttribute(objectName, new Attribute("loader", webLoader)); 4. } 5. else 6. { 7. server.setAttribute(objectName, new Attribute("parentClassLoader", loader)); 8. } 9. 10. server.setAttribute(objectName, new Attribute("delegate", new Boolean(getJava2ClassLoadingCompliance()))); // 设置deletegate属性
说明:
1.WebCtxLoader(ClassLoader encLoader) 2. { 3. this.encLoader = encLoader; 4. this.ctxLoader = new ENCLoader(encLoader); 5. ClassLoader parent = encLoader; 6. while ((parent instanceof RepositoryClassLoader) == false && parent != null) 7. parent = parent.getParent(); 8. this.delegate = (RepositoryClassLoader) parent; //delegate对象设置 9. } 10. 11. 12.public void setWarURL(URL warURL) throws MalformedURLException 13. { 14. this.warURL = warURL; 15. String path = warURL.getFile(); 16. File classesDir = new File(path, "WEB-INF/classes"); 17. if (classesDir.exists()) 18. { 19. delegate.addURL(classesDir.toURL()); //无非都是委托给delegate loader 20. ctxLoader.addURLInternal(classesDir.toURL()); 21. } 22. File libDir = new File(path, "WEB-INF/lib"); 23. if (libDir.exists()) 24. { 25. File[] jars = libDir.listFiles(); 26. int length = jars != null ? jars.length : 0; 27. for (int j = 0; j < length; j++) 28. { 29. delegate.addURL(jars[j].toURL()); //无非都是委托给delegate loader 30. ctxLoader.addURLInternal(jars[j].toURL()); 31. } 32. } 33. }
1.public class WebAppLoader extends org.apache.catalina.loader.WebappLoader 2.{ 3. private String[] filteredPackages = { 4. "org.apache.commons.logging" 5. }; 6. 7. public WebAppLoader() 8. { 9. super(); 10. setLoaderClass(WebAppClassLoader.class.getName()); 11. } 12...... 13.}
tomcat相比于jboss4.05概念上简介了很多,不过tomcat 6版本相比于tomcat 5有一些变化,少了一些shared lib库的概念。
Bootstrap | System | Common / \ Webapp1 Webapp2 ...
一个树状结构,相信大家差不多都知道tomcat默认是以child first装载class,优先载入web中的class类,找不到才会去装载公用类。
下面就来看一下代码的一些实现:
1.public synchronized void start() { 2...... 3. 4.if (getLoader() == null) { 5. WebappLoader webappLoader = new WebappLoader(getParentClassLoader()); 6. webappLoader.setDelegate(getDelegate()); 7. setLoader(webappLoader); 8. } 9...... 10.}
public synchronized void start() {.....if (getLoader() == null) { WebappLoader webappLoader = new WebappLoader(getParentClassLoader()); webappLoader.setDelegate(getDelegate()); setLoader(webappLoader); }.....}
转载地址:http://aimfl.baihongyu.com/