when the process working for two days,StackOverflowError always happen,the stacktrace is below:
{code: java } java .lang.StackOverflowError at java.util.Collections$UnmodifiableCollection.isEmpty(Collections.java:1031) at java.util.Collections$UnmodifiableCollection.isEmpty(Collections.java:1031) ...... at java.util.Collections$UnmodifiableCollection.isEmpty(Collections.java:1031) at java.util.Collections$UnmodifiableCollection.isEmpty(Collections.java:1031) at java.util.Collections$UnmodifiableCollection.isEmpty(Collections.java:1031) at java.util.Collections$UnmodifiableCollection.isEmpty(Collections.java:1031) at java.util.Collections$UnmodifiableCollection.isEmpty(Collections.java:1031) at java.util.Collections$UnmodifiableCollection.isEmpty(Collections.java:1031) at org.hibernate.validator.internal.engine.valueextraction.ValueExtractorResolver.getRuntimeCompliantValueExtractors(ValueExtractorResolver.java:316) at org.hibernate.validator.internal.engine.valueextraction.ValueExtractorResolver.getValueExtractorCandidatesForContainerDetectionOfGlobalCascadedValidation(ValueExtractorResolver.java:177) at org.hibernate.validator.internal.metadata.aggregated.CascadingMetaDataBuilder.build(CascadingMetaDataBuilder.java:227) at org.hibernate.validator.internal.metadata.aggregated.FieldCascadable$Builder.build(FieldCascadable.java:83) at org.hibernate.validator.internal.metadata.aggregated.FieldCascadable$Builder.build(FieldCascadable.java:64) at org.hibernate.validator.internal.metadata.aggregated.PropertyMetaData$Builder.lambda$build$1(PropertyMetaData.java:347) at org.hibernate.validator.internal.metadata.aggregated.PropertyMetaData$Builder$$Lambda$62/1651906449.apply(Unknown Source) at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) at java.util.HashMap$ValueSpliterator.forEachRemaining(HashMap.java:1625) at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481) at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708) at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499) at org.hibernate.validator.internal.metadata.aggregated.PropertyMetaData$Builder.build(PropertyMetaData.java:348) at org.hibernate.validator.internal.metadata.aggregated.PropertyMetaData$Builder.build(PropertyMetaData.java:151) at org.hibernate.validator.internal.metadata.aggregated.BeanMetaDataImpl$BuilderDelegate.build(BeanMetaDataImpl.java:784) at org.hibernate.validator.internal.metadata.aggregated.BeanMetaDataImpl$BeanMetaDataBuilder.build(BeanMetaDataImpl.java:648) at org.hibernate.validator.internal.metadata.BeanMetaDataManager.createBeanMetaData(BeanMetaDataManager.java:192) at org.hibernate.validator.internal.metadata.BeanMetaDataManager.lambda$getBeanMetaData$0(BeanMetaDataManager.java:160) at org.hibernate.validator.internal.metadata.BeanMetaDataManager$$Lambda$53/253243426.apply(Unknown Source) at java.util.concurrent.ConcurrentMap.computeIfAbsent(ConcurrentMap.java:324) at org.hibernate.validator.internal.metadata.BeanMetaDataManager.getBeanMetaData(BeanMetaDataManager.java:159) at org.hibernate.validator.internal.engine.ValidationContext$ValidationContextBuilder.forValidate(ValidationContext.java:566) at org.hibernate.validator.internal.engine.ValidatorImpl.validate(ValidatorImpl.java:155) at com.test.ValidateParameters.validateObject(ValidateParameters.java:31) {code}
The environment is :x86_64 GNU/Linux JRE: 1.8.0_181 hibernate-validator:6.0.13Final And our code is easy,just like this,first get validator in a static block,and then validate paramter for every request param:
{code:java} //get validator Validator validator = Validation.byDefaultProvider() .providerResolver(new OsgiValidationProviderResolver()) .configure().messageInterpolator(resouce) .buildValidatorFactory().getValidator(); //validate parameter,this parameter is an Object,(we think it contains map attribute may have the problem). Set<ConstraintViolation> validateResultSets = validator.validate(parameter); {code}
Our team have view the code,we doubt the following code(ValueExtractorResolver.java, getRuntimeCompliantValueExtractors) may has some problem in Multithreading,why it always happens for a long time? When in thread one,the attribute "valueExtractorDescriptors" is not empty ,and it's type is java.util.map,then it will change to ImmutableSet,then a second thread run "valueExtractorDescriptors.isEmpty()",it will goes to the UnmodifiableCollection.isEmpty,this will recursion,at last it will throw SO Exception.
{code:java} private Set<ValueExtractorDescriptor> getRuntimeCompliantValueExtractors(Class<?> runtimeType, Set<ValueExtractorDescriptor> potentialValueExtractorDescriptors) { if ( nonContainerTypes.contains( runtimeType ) ) { return Collections.emptySet(); } Set<ValueExtractorDescriptor> valueExtractorDescriptors = possibleValueExtractorsByRuntimeType.get( runtimeType ); if ( valueExtractorDescriptors == null ) { //otherwise we just look for maximally specific extractors for the runtime type Set<ValueExtractorDescriptor> possibleValueExtractors = potentialValueExtractorDescriptors .stream() .filter( e -> TypeHelper.isAssignable( e.getContainerType(), runtimeType ) ) .collect( Collectors.toSet() );
valueExtractorDescriptors = getMaximallySpecificValueExtractors( possibleValueExtractors ); }
if ( valueExtractorDescriptors.isEmpty() ) { nonContainerTypes.put( runtimeType, NON_CONTAINER_VALUE ); } else { Set<ValueExtractorDescriptor> extractorDescriptorsToCache = CollectionHelper.toImmutableSet( valueExtractorDescriptors ); possibleValueExtractorsByRuntimeType.put( runtimeType, extractorDescriptorsToCache ); return extractorDescriptorsToCache; }
return valueExtractorDescriptors; } {code} |
|