We use the hibernate validator and dynamically class-loading in our project (by load class into a separate class-loader). After we realise that the class is not required we remove all references to the class and class-loader, then GC collects this.
What we get: Some time after the application starts the java reflection stops working.
java.lang.reflect.UndeclaredThrowableException: null
at com.sun.proxy.$Proxy253.equals(Unknown Source)
at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager$CacheKey.equals(ConstraintValidatorManager.java:287)
at java.util.concurrent.ConcurrentHashMap.get(ConcurrentHashMap.java:940)
at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager.getInitializedValidator(ConstraintValidatorManager.java:104)
at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.getConstraintValidatorNoUnwrapping(ConstraintTree.java:301)
at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.getConstraintValidatorInstanceForAutomaticUnwrapping(ConstraintTree.java:242)
at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.getInitializedConstraintValidator(ConstraintTree.java:163)
at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateConstraints(ConstraintTree.java:116)
at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateComposingConstraints(ConstraintTree.java:396)
at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateConstraints(ConstraintTree.java:98)
at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateConstraints(ConstraintTree.java:87)
at org.hibernate.validator.internal.metadata.core.MetaConstraint.validateConstraint(MetaConstraint.java:73)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateMetaConstraint(ValidatorImpl.java:616)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraint(ValidatorImpl.java:581)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForSingleDefaultGroupElement(ValidatorImpl.java:527)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForDefaultGroup(ValidatorImpl.java:495)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:460)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:410)
at org.hibernate.validator.internal.engine.ValidatorImpl.validate(ValidatorImpl.java:207)
at org.springframework.validation.beanvalidation.SpringValidatorAdapter.validate(SpringValidatorAdapter.java:281)
... Many spring filters calls ...
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.multipart.support.MultipartFilter.doFilterInternal(MultipartFilter.java:122)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at *someAwesomePackage*.microservice.rest.spring.webapp.CabinetRequestFilter.doFilterInternal(CabinetRequestFilter.java:98)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.reflect.InvocationTargetException: null
at sun.reflect.GeneratedMethodAccessor268.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.hibernate.validator.internal.util.annotationfactory.AnnotationProxy.invoke(AnnotationProxy.java:69)
... 260 common frames omitted
Caused by: java.lang.NullPointerException: null
at org.hibernate.validator.internal.util.annotationfactory.AnnotationProxy.getAnnotationMemberValue(AnnotationProxy.java:248)
at org.hibernate.validator.internal.util.annotationfactory.AnnotationProxy.equals(AnnotationProxy.java:104)
... 264 common frames omitted
Error happens in this place (method from java.lang.Class.java):
private static Method searchMethods(Method[] methods,
String name,
Class<?>[] parameterTypes) {
Method res = null;
String internedName = name.intern();
for (int i = 0; i < methods.length; i++) {
Method m = methods[i];
if (m.getName() == internedName
&& arrayContentsEq(parameterTypes, m.getParameterTypes())
&& (res == null
|| res.getReturnType().isAssignableFrom(m.getReturnType())))
res = m;
}
return (res == null ? res : getReflectionFactory().copyMethod(res));
}
Class has method, but the comparison of m.getName () == internedName
is false.
Comparison returns false because names of the methods are not interned.
If I calling m.getName (). Intern () == internedName
from debug, it returns true. But the method 'searchMethods' is from 'java.lang.Class'.
This always happens after some time from the application start.
Did anybody encounter such a problem?
EDIT (25/12/2017):
Not only hibernate validator failed, xml parsing failed too!
XML example:
<SELFCARE>
<SESSION_ID>***</SESSION_ID>
</SELFCARE>
Mapping example:
@XmlRootElement(name = "SELFCARE")
@XmlAccessorType(XmlAccessType.FIELD)
public class Session {
@XmlElement(name = "SESSION_ID")
private String sessionId;
}
Parsing exception:
WARN 2017.12.25 20:00:05.991 +0300 org.apache.cxf.jaxrs.provider.AbstractJAXBProvider javax.xml.bind.UnmarshalException
- with linked exception:
[com.sun.istack.SAXParseException2; lineNumber: 1; columnNumber: 1; unexpected element (uri:"", local:"SELFCARE"). Expected elements are <{}SELFCARE>]
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.handleStreamException(UnmarshallerImpl.java:483)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:417)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:386)
at org.apache.cxf.jaxrs.provider.JAXBElementProvider.unmarshalFromInputStream(JAXBElementProvider.java:294)
at org.apache.cxf.jaxrs.provider.JAXBElementProvider.doUnmarshal(JAXBElementProvider.java:245)
But mapping is correct and working, if reflection is working...
From the stacktrace, I suspect you're using HV 5.x. Am I right?
The issue seems to be related to the fact that you have a proxy. I think it's probably related to the annotation being part of the key.
Could you try HV 6.0.7.Final? We got rid of using the annotation in the cache key here so it might solve your issue.
Be careful, we changed the groupId: it's now org.hibernate.validator (instead of org.hibernate) - be careful if the HV dependency is coming transitively from another artifact, add exclusions if need be.
You also need the javax.el dependency:
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.el</artifactId>
<version>3.0.1-b08</version>
</dependency>
(be careful, there might be other javax.el artifacts in your dependencies so be sure to have only this one - the dependency hierarchy view of Eclipse might help)
You also need validation-api 2.0.1.Final (it comes transitively with HV but you might have to change the version if you explicitly declared it).
Other than that, you shouldn't have any compatibility issue (except if you were using experimental features such as value handling): it's a drop in replacement. HV 6 is also significantly faster so it should be a win-win situation.
Feel free to report any issue with your upgrade here, I'll help.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With