Inline classes on openjdk


#1

Hej, I am building a spring boot app with kotlin and wanted to use inline classes. I made a spring data repository that has a method as follows: fun getBy(name: GameName) where GameName is an inline class inline class GameName(val value: String)

And everything works locally, where i am running jdk 1.8.0_181-b13. But when i deploy it to google cloud, the spring boot app doesn’t start up. Google cloud seems to be running openjdk 1.8.0_181.

When i decompile the code locally it looks like this:
public GameConfigurationEntity getBy_00UsoVY/* $FF was: getBy-00UsoVY*/(@NotNull String gameName, @NotNull UUID id) { ... }

But on google cloud i get the following error:
Caused by: java.lang.ClassFormatError: Illegal method name "getByName-MZoZWhM"

So it seems locally it uses _ while on google cloud it uses - and - is not a valid charactar in a method name.

Anyone else had this?


#2

It is a valid character in the JVM spec (just not in the JLS/ Java Language Spec). It seems that google cloud does further stuff with your java classes as openjdk is the basis for oracles jdk and should just do this fine.


#3

Yeah, i tried running in an openjdk based docker and that seems to work. so it must be something that google cloud does. Which is strange as it runs it in a debian openjdk based container too.


#4

Answered here: https://stackoverflow.com/questions/53098190/inline-classes-generate-strange-names-on-openjdk#comment93094344_53098190


#5

Looking at the question on stackoverflow it is a problem where a class file is declared invalid by the classloader. This implies that the classloader is incorrect per the JVM spec in terms of allowed characters in method names, and changed from plain openjdk. In other words, this is a bug in the google cloud platform.


#6

Thanks for the reply. Do you guys have any suggestion on how to proceed? Maybe a strange question as it seems to be more of a google problem then a kotlin problem. But i know JetBrains has a close relation with google.


#7

File a bug with google. In the meantime you could explore bytecode rewriting to normalize names. Btw. I’m assuming the issue is with any method that takes inline classes, not spring injected ones (in which case you could just have a method that doesn’t take an inline class as I suspect spring doesn’t support inline classes yet anyway)


#8

I tried with methods on normal spring beans as well and they had the same problem. I ll see if i can log a bug with google.


#9

I tried to make a tiny example for my bug report so i came up with this:

@SpringBootApplication
class DemoApplication
fun main(args: Array<String>) {
    runApplication<DemoApplication>(*args)
}

@RestController
class SomeController(private val someService: SomeService) {

    @GetMapping()
    fun get() = someService.doSomething(SomeInlineClass("world"))
}

@Service
class SomeService() {

    fun doSomething(something: SomeInlineClass) = "hello" + something.value

}

inline class SomeInlineClass(val value: String)

And this seems to work perfectly fine on google cloud. So i think i will have to investigate further to see what exactly was wrong with the previous code.

Thanks for all the help upto now, you might hear from me again :wink:


#10

My project does not run on docker/openjdk, but it works locally on macOS without docker. So it’s not only google cloud doning something different.
Will investigate further…


#11

Are you using the installed-by-default jdk on macos? This default jdk is known to have various compatibility issues (for example encryption/ssl is crippled).


#12

It’s JDK 1.8.0 manually downloaded from oracle.com