Affects: Spring version 5.2
Hello, in a particular docker environment using Oracle JDK1.8.0_261. When I run (as the main method)
ThreadPoolTaskExecutor bean = new ThreadPoolTaskExecutor();
ProxyFactoryBean factory = new ProxyFactoryBean();
factory.setProxyTargetClass(true);
factory.setTarget(bean);
Object x = factory.getObject();
I get an exception like so
Caused by: java.lang.VerifyError: Stack map does not match the one at exception handler 122
Exception Details:
Location:
org/springframework/scheduling/concurrent/ThreadPoolTaskExecutor$$EnhancerBySpringCGLIB$$c6fcfbe9.submit(Ljava/lang/Runnable;)Ljava/util/concurrent/Future; @122: astore
Reason:
Type 'java/util/concurrent/Future' (current frame, locals[2]) is not assignable to integer (stack map, locals[2])
Current Frame:
bci: @109
flags: { }
locals: { 'org/springframework/scheduling/concurrent/ThreadPoolTaskExecutor$$EnhancerBySpringCGLIB$$c6fcfbe9', 'java/lang/Runnable', 'java/util/concurrent/Future', 'java/lang/Runnable', 'org/springframework/scheduling/concurrent/ThreadPoolTaskExecutor$$EnhancerBySpringCGLIB$$c6fcfbe9', 'java/lang/Runnable' }
stack: { 'java/lang/Exception' }
Stackmap Frame:
bci: @122
flags: { }
locals: { 'org/springframework/scheduling/concurrent/ThreadPoolTaskExecutor$$EnhancerBySpringCGLIB$$c6fcfbe9', 'java/lang/Runnable', integer, 'java/lang/Runnable' }
stack: { 'java/lang/Throwable' }
Bytecode:
0x0000000: 014e 033d b804 0a3a 0419 04c6 001a 2bc6
0x0000010: 0016 b204 102a b604 159a 000c 2b4e 1904
0x0000020: 2bb6 041b 4ca7 0006 b604 1e2a 3a04 2b3a
0x0000030: 0519 04b4 0034 59c7 000e 5719 04b8 0038
0x0000040: 1904 b400 3459 c600 1f19 04b2 003a 04bd
0x0000050: 003c 5903 1905 53b2 003e b900 4405 00c0
0x0000060: 0046 a700 1019 0419 05b7 0032 4d57 2ca7
0x0000070: 0003 3a04 013a 05a7 0008 3a05 013a 042d
0x0000080: c600 2519 05c0 0402 c104 209a 000e 1905
0x0000090: c004 02c1 03ea 9900 0f2d 4cb2 0410 2ab6
0x00000a0: 0423 a700 0b03 a700 07b6 041e 033d 1c99
0x00000b0: 0006 a7ff 7919 05c6 0006 1905 bf19 04b0
0x00000c0:
Exception Handler Table:
bci [4, 40] => handler: 40
bci [49, 114] => handler: 122
bci [127, 169] => handler: 169
Stackmap Table:
append_frame(@4,Integer,Object[#1028])
append_frame(@37,Object[#1047])
full_frame(@40,{Object[#2],Object[#1028],Integer,Object[#1028]},{Object[#999]})
same_frame(@43)
append_frame(@49,Object[#2],Object[#1028])
same_locals_1_stack_item_frame(@69,Object[#64])
same_locals_1_stack_item_frame(@101,Object[#64])
full_frame(@114,{Object[#2],Object[#1028],Integer,Object[#1028]},{Object[#70]})
same_locals_1_stack_item_frame(@122,Object[#999])
append_frame(@127,Object[#70],Object[#999])
same_frame(@153)
same_frame(@165)
same_locals_1_stack_item_frame(@169,Object[#999])
same_locals_1_stack_item_frame(@173,Integer)
same_frame(@181)
same_frame(@189)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:348)
at org.springframework.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:571)
at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:363)
at org.springframework.cglib.proxy.Enhancer.generate(Enhancer.java:585)
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:110)
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:108)
at org.springframework.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61)
... 21 more
The bytecode looks all wrong, I don't think the submit method of the proxy should even have an exception handler, it doesn't seem to when I capture the proxied class on my own computer.
It works fine normally (i.e. running it on my machine). It used to work on the container when using Spring 5.1
What could cause this? I am not going to be able to provide a docker image you can see this in, I don't control the image where the issue is.
I'm using Gradle to make the jar, only dependencies are
compile("org.springframework:spring-context:5.2.9.RELEASE")
compile("org.springframework:spring-core:5.2.9.RELEASE")
compile("org.springframework:spring-aop:5.2.9.RELEASE")
I tried reading the class file generation code for a hint of something platform dependent, but it's complex of course...
Comment From: sbrannen
Out of curiosity, why are you proxying ThreadPoolTaskExecutor
?
What's the use case for that?
Comment From: itsyaboiyeah
Hey, it's not my idea. The above is just a minimal reduction of the actual issue in a real app. The thing which proxies ThreadPoolTaskExecutor in reality is opentracing
https://github.com/opentracing-contrib/java-spring-cloud/blob/master/instrument-starters/opentracing-spring-cloud-core/src/main/java/io/opentracing/contrib/spring/cloud/async/ExecutorBeanPostProcessor.java#L84
I don't claim to know what it's for exactly but it seems like it makes sense in this context.
Comment From: sbrannen
OK. Now I see that they have a TracedThreadPoolTaskExecutor.
Thanks for sharing the use case.
Comment From: sbrannen
in a particular docker environment using Oracle JDK1.8.0_261.
Is the JDK modified in any way?
Can you provide specific details about the Docker container you are using (exact versions, any special flags for the JVM, etc.)?
Comment From: itsyaboiyeah
The JDK is not modified in any way, I can't provide details of the container I'm afraid it's a client side docker image which I have no visibility of, that being said, given that it's oracle jdk on a docker container which seems unusual, perhaps the base is one of the images that Oracle themselves provide. There are no special flags for the JVM.
The bytecode listed in the stack trace doesn't look anything like the bytecode of the proxied class when I do it on my machine btw.
Comment From: itsyaboiyeah
Is there any progress on this? For the time being we've disabled the bit of opentracing that tries to make this proxy. But of course it is quite unnerving the prospect that any proxy creation could fail, or indeed perhaps proxies are being made which pass validation but are incorrect.
Comment From: snicoll
@itsyaboiyeah I am afraid without a reproducer, it is going to be hard to make any progress as we're left wondering what the problem might be. Given the issue isn't actionable, I am going to close it but we can reopen if a reproducer is provided.