Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jackson fails to deserialize Kotlin classes that contain spaces in the name #2228

Closed
xaviarias opened this issue Jan 20, 2019 · 4 comments
Closed

Comments

@xaviarias
Copy link

xaviarias commented Jan 20, 2019

Similar issues have been reported but not for this specific test case.

The problem arises when deserializing a Kotlin class name with spaces.

I have created a repo with the required code to reproduce the issue.

Signature Parse error: expected '<' or ';' but got  
	Remaining input:  a test method name contains spaces Jackson fails to deserialize a local data class$LocalDataClass;>;
java.lang.reflect.GenericSignatureFormatError: Signature Parse error: expected '<' or ';' but got  
	Remaining input:  a test method name contains spaces Jackson fails to deserialize a local data class$LocalDataClass;>;
	at java.base/sun.reflect.generics.parser.SignatureParser.error(SignatureParser.java:124)
	at java.base/sun.reflect.generics.parser.SignatureParser.parsePackageNameAndSimpleClassTypeSignature(SignatureParser.java:337)
	at java.base/sun.reflect.generics.parser.SignatureParser.parseClassTypeSignature(SignatureParser.java:304)
	at java.base/sun.reflect.generics.parser.SignatureParser.parseFieldTypeSignature(SignatureParser.java:283)
	at java.base/sun.reflect.generics.parser.SignatureParser.parseFieldTypeSignature(SignatureParser.java:277)
	at java.base/sun.reflect.generics.parser.SignatureParser.parseTypeArgument(SignatureParser.java:420)
	at java.base/sun.reflect.generics.parser.SignatureParser.parseTypeArguments(SignatureParser.java:380)
	at java.base/sun.reflect.generics.parser.SignatureParser.parsePackageNameAndSimpleClassTypeSignature(SignatureParser.java:335)
	at java.base/sun.reflect.generics.parser.SignatureParser.parseClassTypeSignature(SignatureParser.java:304)
	at java.base/sun.reflect.generics.parser.SignatureParser.parseClassSignature(SignatureParser.java:213)
	at java.base/sun.reflect.generics.parser.SignatureParser.parseClassSig(SignatureParser.java:156)
	at java.base/sun.reflect.generics.repository.ClassRepository.parse(ClassRepository.java:57)
	at java.base/sun.reflect.generics.repository.ClassRepository.parse(ClassRepository.java:41)
	at java.base/sun.reflect.generics.repository.AbstractRepository.<init>(AbstractRepository.java:74)
	at java.base/sun.reflect.generics.repository.GenericDeclRepository.<init>(GenericDeclRepository.java:49)
	at java.base/sun.reflect.generics.repository.ClassRepository.<init>(ClassRepository.java:53)
	at java.base/sun.reflect.generics.repository.ClassRepository.make(ClassRepository.java:70)
	at java.base/java.lang.Class.getGenericInfo(Class.java:3028)
	at java.base/java.lang.Class.getGenericSuperclass(Class.java:938)
	at com.fasterxml.jackson.core.type.TypeReference.<init>(TypeReference.java:33)
	at GenericSignatureFormatErrorTest$when a test method name contains spaces Jackson fails to deserialize a local data class$$inlined$readValue$1.<init>(Extensions.kt:18)
	at GenericSignatureFormatErrorTest.when a test method name contains spaces Jackson fails to deserialize a local data class$jackson_bug(GenericSignatureFormatErrorTest.kt:22)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:532)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:115)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:171)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:167)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:114)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:59)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$4(NodeTestTask.java:108)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:98)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:74)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$4(NodeTestTask.java:112)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:98)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:74)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$4(NodeTestTask.java:112)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:98)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:74)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:220)
	at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:188)
	at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:202)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:181)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:102)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:82)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:78)
	at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
	at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
	at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
	at com.sun.proxy.$Proxy2.stop(Unknown Source)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.stop(TestWorker.java:132)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
	at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:175)
	at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:157)
	at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404)
	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
	at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
	at java.base/java.lang.Thread.run(Thread.java:834)
@cowtowncoder
Copy link
Member

Quick question: where is the name with space in it? Is it something Kotlin compiler generates as a helper or something else?

I am bit worried wrt reproduction as there does not seem to be anything actually using class name for anything... so I don't know what could be done to resolve it. If there is something, it probably would need to be by Kotlin module too.

@xaviarias
Copy link
Author

xaviarias commented Jan 23, 2019

hi @cowtowncoder, as a minimal test case the class to deserialize that generates the exception is defined within the scope of the test method, so its name contains the test method name itself:

a test method name contains spaces Jackson fails to deserialize a local data class$LocalDataClass;>;

I guess Java class names are not expected to contain spaces, so you are probably right and is a Kotlin issue, but I found a similar bug so I was hoping it could be a Jackson databind issue.

@cowtowncoder
Copy link
Member

Right, I was at first thinking it might be related to that piece of code.

Unfortunately as you can see from the stack trace, exception comes from deep within bowels of JDK (I think). So I am not sure what sure what Jackson could do.

But the reference to Kotlin module has more to do with sort of division of labor: similar to Scala module, Kotlin module handles some of differences (like added introspection capabilities and requirements), especially things core databind does not have access to (in the sense it not having any Kotlin or Scala-specific code).

Looking at stack trace again, I think triggering of the exception might even work simply by trying to construct TypeReference with space-containing class as type parameter.
Not sure how much knowing that helps us, given that it's still JDK (or JVM?) that barfs, without Jackson having much say. This assuming I read stack trace information correctly.

@xaviarias
Copy link
Author

Thanks for your answer, yes definitely I would say is a JDK or Kotlin issue. Or even more JDK cause Kotlin is allowed to define a class with spaces in its name, so the Java Class should be aware of that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants