`

请您先登录,才能继续操作

java.lang.reflect.MalformedParameterizedTypeException

    博客分类:
  • JAVA
 
阅读更多

尝试spring3.0的新特性,在原本是spring207,spring256混杂的工程里引入了spring3.x然后很简单的一个bean初始化失败,报以下异常

 

Caused by: java.lang.reflect.MalformedParameterizedTypeException
	at sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl.validateConstructorArguments(Unknown Source)
	at sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl.<init>(Unknown Source)
	at sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl.make(Unknown Source)
	at sun.reflect.generics.factory.CoreReflectionFactory.makeParameterizedType(Unknown Source)
	at sun.reflect.generics.visitor.Reifier.visitClassTypeSignature(Unknown Source)
	at sun.reflect.generics.tree.ClassTypeSignature.accept(Unknown Source)
	at sun.reflect.generics.repository.ClassRepository.getSuperInterfaces(Unknown Source)
	at java.lang.Class.getGenericInterfaces(Unknown Source)
	at org.springframework.core.GenericTypeResolver.getTypeVariableMap(GenericTypeResolver.java:151)
	at org.springframework.core.GenericTypeResolver.resolveParameterType(GenericTypeResolver.java:81)
	at org.springframework.beans.GenericTypeAwarePropertyDescriptor.getWriteMethodParameter(GenericTypeAwarePropertyDescriptor.java:109)
	at org.springframework.beans.GenericTypeAwarePropertyDescriptor.getPropertyType(GenericTypeAwarePropertyDescriptor.java:91)
	at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:138)
	at org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:386)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.convertForProperty(AbstractAutowireCapableBeanFactory.java:1289)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1250)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1010)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:472)
	... 14 more

 

    然后找出抛出异常的jdk源码

 

 

private void validateConstructorArguments() {
     TypeVariable[] formals = this.rawType.getTypeParameters();
 
   if (formals.length != this.actualTypeArguments.length) {
     throw new MalformedParameterizedTypeException();
   }
    for (int i = 0; i < this.actualTypeArguments.length; ++i);
}

 

利用jdk的fastdebug版本可以看到formals.length == 0 而this.actualTypeArguments.length ==1

并且:

actualTypeArguments 是 【interface org.springframework.core.task.TaskExecutor】

rawType 是【interface org.springframework.beans.factory.FactoryBean】并且不具有泛型参数,故猜测这里需要一个泛型参数是TaskExecutor的FactoryBean。

 

ok,下面开始找出这个bean的实例化是如何进行的,这个bean是spring3.0中新提供的,配置方式如下:

 

<task:executor id="myExecutor" pool-size="5"/>
 

 

通过debug跟踪到spring的BeanDefinitionParserDelegate这个类,然后看如下这个方法

 

 

public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
		String namespaceUri = ele.getNamespaceURI();
		NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
		if (handler == null) {
			error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
			return null;
		}
		return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
	}
 

为了跟踪这个bean的默认bean实现,我们看他的NamespaceHandler是什么,通过看DefaultNamespaceHandlerResolver这个类可以得知,所有的handler都是从META-INF/spring.handlers文件中读出的,同时如果你打开了debug log的话可以看到他会打印出所有默认的handler,例如打印如下

 

 

Loaded mappings [{http://www.springframework.org/schema/p=org.springframework.beans.factory.xml.SimplePropertyNamespaceHandler, http://www.springframework.org/schema/util=org.springframework.beans.factory.xml.UtilNamespaceHandler, http://www.springframework.org/schema/jee=org.springframework.ejb.config.JeeNamespaceHandler, http://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler, http://www.springframework.org/schema/cache=org.springframework.cache.config.CacheNamespaceHandler, http://www.springframework.org/schema/c=org.springframework.beans.factory.xml.SimpleConstructorNamespaceHandler, http://www.springframework.org/schema/tx=org.springframework.transaction.config.TxNamespaceHandler, http://www.springframework.org/schema/task=org.springframework.scheduling.config.TaskNamespaceHandler, http://www.springframework.org/schema/jms=org.springframework.jms.config.JmsNamespaceHandler, http://www.springframework.org/schema/lang=org.springframework.scripting.config.LangNamespaceHandler, http://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler}]

 

这里就有我这次使用到的TaskNamespaceHandler 然后依次找到了 ExecutorBeanDefinitionParser这个类,看到里面的getBeanClassName方法返回的是org.springframework.scheduling.config.TaskExecutorFactoryBean。同时这个类实现了FactoryBean<TaskExecutor>这个接口。发现原来已经给了一个带泛型的FactoryBean了。那到底是哪里的问题呢,继续跟踪。。

 

借助jdk源码以及fastdebug版本,跟踪到sun.reflect.generics.repository.ClassRepository 和 sun.reflect.generics.factory.CoreReflectionFactory这个2个类,看到里面有对应的泛型信息,但是取到的却不对,继续跟踪到Class这个类,其中核心的会使用这个方法

 

public TypeVariable<Class<T>>[] getTypeParameters() {
	if (getGenericSignature() != null) 
	    return (TypeVariable<Class<T>>[])getGenericInfo().getTypeParameters();
	else
	    return (TypeVariable<Class<T>>[])new TypeVariable[0];
    }
 

 

debug看到第一个if没通过,所以返回一个空的,那第一个getGenericSignature方法就至关重要了。下面debug这个方法,以下是方法签名:

 // Generic signature handling
    private native String getGenericSignature();

 一看是native方法,好吧直接断了我继续debug的耐心了。不过到这里已经有了一些眉目了,针对这个问题产生的原因,既然是从class的本地元信息中获得泛型信息,那说明这个class文件可能真的就不存在这些元信息,那这样可能就是jar包污染了。然后将spring 207 256的jar包都删除,只保留3.0的,重新debug发现,这次native就有返回值了。程序不再报错了。

 

 

总结:以后遇到这个异常,多半先检查下jar包版本是否存在多个版本,然后最后统一只使用到其中的一个版本来测试,这种问题太难排查了,先把环境搞干净了再debug吧。

分享到:
评论
4 楼 aptech406328627 2016-07-08  
大神,请接收我的膜拜吧,纠结了两天的问题,就这么让你给解决了
3 楼 xukunddp 2016-03-22  
谢谢1楼,我也遇到,搞定了
2 楼 u012273744 2015-04-01  
楼主太厉害了,我也遇到了
1 楼 daoyongyu 2014-08-28  
楼主强人,确实是jar包冲突的问题,我也遇到了。
项目中用到阿里的dubbo框架,它引用的是spring 2.5.6.SEC03,而我项目中有用spring 3.1.x,所以导致冲突。 在maven中将spring的依赖去除了。

             <dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.4.9</version>
<exclusions>
<exclusion>
<artifactId>spring</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
</dependency>

相关推荐

Global site tag (gtag.js) - Google Analytics