Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java 8 reflection doesn't work

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...

like image 728
Alexey Avatar asked Nov 08 '22 12:11

Alexey


1 Answers

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.

like image 106
Guillaume Smet Avatar answered Nov 14 '22 22:11

Guillaume Smet