问题描述
使用Spring Boot构建web app,Controller中通过dubbo消费端远程调用服务端,使用注解进行参数校验,如getName(@NotNull String id)。
在调用过程中始终报错:
java.lang.RuntimeException: XXXService_GetNameParameter: frozen class (cannot edit)
at javassist.ClassPool.checkNotFrozen(ClassPool.java:617) ~[javassist-3.21.0-GA.jar:?]
at javassist.ClassPool.makeClass(ClassPool.java:859) ~[javassist-3.21.0-GA.jar:?]
at javassist.ClassPool.makeClass(ClassPool.java:836) ~[javassist-3.21.0-GA.jar:?]
at com.alibaba.dubbo.validation.support.jvalidation.JValidator.getMethodParameterBean(JValidator.java:166)
问题分析
- 初步判断和dubbo版本无关,应该是一个bug。报错的原因是再次尝试查找动态生成的类时,应该能找到,实际上因为classloader的原因无法找到。即com.alibaba.dubbo.validation.support.jvalidation.JValidator第163行:
parameterClass = (Class<?>) Class.forName(parameterClassName, true, clazz.getClassLoader());
这里应该能够找到parameterClass,而不是再次抛出ClassNotFoundException。
- 出现ClassNotFoundException的原因,是由于在生成参数类XXXService_GetNameParameter的时候,没有传入该参数的接口的classLoader(即clazz.getClassLoader),而是使用了默认的Context ClassLoader。
- 建议修改JValidator第202行为:
parameterClass = ctClass.toClass(clazz.getClassLoader(), null);传入接口的classLoader,保证其一致性。
问题描述
使用Spring Boot构建web app,Controller中通过dubbo消费端远程调用服务端,使用注解进行参数校验,如getName(@NotNull String id)。
在调用过程中始终报错:
java.lang.RuntimeException: XXXService_GetNameParameter: frozen class (cannot edit)
at javassist.ClassPool.checkNotFrozen(ClassPool.java:617) ~[javassist-3.21.0-GA.jar:?]
at javassist.ClassPool.makeClass(ClassPool.java:859) ~[javassist-3.21.0-GA.jar:?]
at javassist.ClassPool.makeClass(ClassPool.java:836) ~[javassist-3.21.0-GA.jar:?]
at com.alibaba.dubbo.validation.support.jvalidation.JValidator.getMethodParameterBean(JValidator.java:166)
问题分析
parameterClass = (Class<?>) Class.forName(parameterClassName, true, clazz.getClassLoader());这里应该能够找到parameterClass,而不是再次抛出ClassNotFoundException。
parameterClass = ctClass.toClass(clazz.getClassLoader(), null);传入接口的classLoader,保证其一致性。