5

Wir verwenden den Hibernate-Validator und laden dynamisch in unserem Projekt (nach Ladeklasse in einen separaten Klassenlader). Nachdem wir erkannt haben, dass die Klasse nicht benötigt wird, entfernen wir alle Verweise auf die Klasse und den Klassenlader, und GC sammelt diese.java 8 reflection funktioniert nicht

Was wir bekommen: Einige Zeit nach dem Start der Anwendung funktioniert die Java-Reflektion nicht mehr.

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 

Fehler passiert an diesem Ort (Methode von 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)); 
} 

Klasse Methode hat, aber der Vergleich von m.getName() == internedName ist falsch. Der Vergleich gibt false zurück, weil die Namen der Methoden nicht interniert sind.

Wenn ich m.getName(). Intern() == internedName von debug aufrufen, wird True zurückgegeben. Aber die Methode 'searchMethods' stammt von 'java.lang.Class'.

Dies geschieht immer nach einiger Zeit ab dem Start der Anwendung.

Hat jemand auf ein solches Problem gestoßen?

EDIT (25/12/2017): zu

Nicht nur Validator fehlgeschlagen Hibernate, fehlgeschlagen XML-Analyse!

XML-Beispiel:

<SELFCARE> 
    <SESSION_ID>***</SESSION_ID> 
</SELFCARE> 

Mapping Beispiel:

@XmlRootElement(name = "SELFCARE") 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Session { 

    @XmlElement(name = "SESSION_ID") 
    private String sessionId; 
} 

Parsing Ausnahme:

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) 

Aber Mapping korrekt ist und funktioniert, wenn Reflexion funktioniert ...

+0

Haben Sie versucht, m.getName(). Intern() == internedName? Aus der Dokumentation: Wenn die interne Methode aufgerufen wird, wenn der Pool bereits eine Zeichenfolge enthält, die diesem String-Objekt entspricht, wie von der Methode equals (Object) bestimmt, wird die Zeichenfolge aus dem Pool zurückgegeben. Andernfalls wird dieses String-Objekt zum Pool hinzugefügt, und eine Referenz auf dieses String-Objekt wird zurückgegeben. Daraus folgt, dass für zwei beliebige Strings s und t, s.intern() == t.intern() genau dann wahr ist, wenn s.equals (t) wahr ist. – Kaushal

+0

Verschiebt/delegiert Ihr Class Loader das Laden an den übergeordneten Klassenlader? – diginoise

+0

Warum nicht equals anstelle von '==' verwenden? Kannst du die Zeile mit der NullpointerException markieren, von meinem Standpunkt aus führt das String Interning nicht dazu – CoronA

Antwort

1

Von der st acktrace, ich vermute du verwendest HV 5.x. Habe ich recht?

Das Problem scheint mit der Tatsache verbunden zu sein, dass Sie einen Proxy haben. Ich denke, es hängt wahrscheinlich damit zusammen, dass die Anmerkung Teil des Schlüssels ist.

Können Sie HV 6.0.7.Final versuchen? Wir haben die Annotation im Cache-Schlüssel entfernt, um Ihr Problem zu lösen.

Seien Sie vorsichtig, wir haben die groupId geändert: es ist jetzt org.hibernate.validator (statt org.hibernate) - seien Sie vorsichtig, wenn die HV-Abhängigkeit transitiv von einem anderen Artefakt kommt, fügen Sie bei Bedarf Ausschlüsse hinzu.

Sie müssen auch die javax.el Abhängigkeit:

<dependency> 
    <groupId>org.glassfish</groupId> 
    <artifactId>javax.el</artifactId> 
    <version>3.0.1-b08</version> 
</dependency> 

(vorsichtig sein, könnte es sein, andere javax.el Artefakte in Ihre Abhängigkeiten so sicher sein, nur um diese eine - die Abhängigkeitshierarchie Ansicht von Eclipse könnte helfen)

Sie benötigen auch validation-api 2.0.1.Final (es kommt transitiv mit HV, aber Sie müssen möglicherweise die Version ändern, wenn Sie es explizit deklariert haben).

Abgesehen davon sollten Sie kein Kompatibilitätsproblem haben (außer wenn Sie experimentelle Funktionen wie Wertverarbeitung verwenden): es ist ein Ersatztropfen. HV 6 ist auch bedeutend schneller, also sollte es eine Win-Win-Situation sein.

Fühlen Sie sich frei, jedes Problem mit Ihrem Upgrade hier zu melden, ich werde helfen.

+0

Guillaume Smet, danke, es funktioniert. Aber App scheitern alle gleich. @ aleksey-shipilev pls Hilfe! – Inv3r