Hessian/Burlap: is an unknown class in WebappClassLoader

警告(并不是错误):警告: Hessian/Burlap:'com.shine.exp.dto.ExpIdCardDTO' is an unknown class in WebappClassLoader

  delegate: false

  repositories:

    /WEB-INF/classes/

----------> ParentClassloader:

java.net.FactoryURLClassLoader@68ad80cf

:

java.lang.ClassNotFoundException:com.shine.exp.dto.ExpIdCardDTO


场景重现:我的一个Service应用中将某个接口发布为Hessian服务,在这个接口中有一个参数Object dataObj,在另一个Web应用中去调用这个服务,但传入的dataObj是ExpIdCardDTO类型的,就会报如上警告。

public Long saveBusiDataWithCondition(String sessionId, int appId, String appWfCode, String uniqueId,
            Object dataObj, boolean isSaveItems) throws ShineException;


原因:客户端在调用服务时会将参数自动序列化,服务提供方在反序列化时无法以最有效的方式反序列话,就会产生如上警告。但我们的程序还是行之有效的:

PropertyDescriptor[] propertyDescriptors = PropertyUtils.getPropertyDescriptors(dataObj);
			for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
				String proTypeName = propertyDescriptor.getPropertyType().getName();
				//判断是否是基础类型
				if(AttributeUtil.isBaseType(proTypeName)){
					//To Do
				}
			}

注意Map对象是不可序列化的,因此dataObj只能对其子类,如 HashMap有特殊处理.

if (dataObj instanceof Map) {
                Map<String, Object> mapData = (Map<String, Object>) dataObj;
                //To Do
            }


附上Tomcat的类装载原理:

- Tomcat的类载入器的结构

TomcatServer在启动的时候将构造一个ClassLoader树,以保证模块的类库是私有的

TomcatServer的ClassLoader结构如下:

        +-----------------------------+

 

        |         Bootstrap           |

 

        |             |               |

 

        |          System             |

 

        |             |               |

 

        |          Common             |

 

        |         /      \            |

 

        |     Catalina Shared        |

 

        |               /   \        |

 

        |          WebApp1 WebApp2   |

 

        +-----------------------------+

 

其中:

- Bootstrap -载入JVM自带的类和$JAVA_HOME/jre/lib/ext/*.jar

- System -载入$CLASSPATH/*.class

- Common -载入$CATALINA_HOME/common/...,它们对TOMCAT和所有的WEB APP都可见

- Catalina -载入$CATALINA_HOME/server/...,它们仅对TOMCAT可见,对所有的WEB APP都不可见

- Shared -载入$CATALINA_HOME/shared/...,它们仅对所有WEB APP可见,对TOMCAT不可见(也不必见)

- WebApp -载入ContextBase?/WEB-INF/...,它们仅对该WEB APP可见

 

2 - ClassLoader的工作原理

 

每个运行中的线程都有一个成员contextClassLoader,用来在运行时动态地载入其它类

系统默认的contextClassLoader是systemClassLoader,所以一般而言java程序在执行时可以使用JVM自带的类、$JAVA_HOME/jre/lib/ext/中的类和$CLASSPATH/中的类

可以使用Thread.currentThread().setContextClassLoader(...);更改当前线程的contextClassLoader,来改变其载入类的行为

 

ClassLoader被组织成树形,一般的工作原理是:

1)线程需要用到某个类,于是contextClassLoader被请求来载入该类

2)contextClassLoader请求它的父ClassLoader来完成该载入请求

3)如果父ClassLoader无法载入类,则contextClassLoader试图自己来载入

 

注意:WebApp?ClassLoader的工作原理和上述有少许不同:

它先试图自己载入类(在ContextBase?/WEB-INF/...中载入类),如果无法载入,再请求父ClassLoader完成

 

由此可得:

- 对于WEBAPP线程,它的contextClassLoader是WebApp?ClassLoader

- 对于TomcatServer线程,它的contextClassLoader是CatalinaClassLoader

 

3 类的查找

 

ClassLoader类中loadClass方法为缺省实现,用下面的顺序查找类:

1、调用findLoadedClass方法来检查是否已经被加载。如果没有则继续下面的步骤。

2、如果当前类装载器有一个指定的委托父装载器,则用委托父装载器的loadClass方法加载类,也就是委托给父装载器加载相应的类。

3、如果这个类装载器的委托层级体系没有一个类装载器加载该类,则使用类装载器定位类的特定实现机制,调用findClass方法来查找类。


阅读更多

没有更多推荐了,返回首页