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

IllegalStateException: Invisible parameter type of kotlin.jvm.internal.DefaultConstructorMarker #776

Closed
henrik242 opened this issue Oct 1, 2017 · 15 comments

Comments

@henrik242
Copy link
Contributor

henrik242 commented Oct 1, 2017

I have a Kotlin class:

open class SomeClass(val cheese: String = "brie") {
    fun foo() = "bar"
}

... and a Spock test:

class OpenTest extends Specification {

    def "should be able to mock"() {
      given:
        def someMock = Mock(SomeClass)
        someMock.foo() >> "cheese"

      expect: "that we actually can mock it"
        someMock.cheese == "brie"
        someMock.foo() == "cheese
    }
}

... using the following Gradle dependencies:

testCompile(
    "org.spockframework:spock-core:1.1-groovy-2.4",
    "net.bytebuddy:byte-buddy:1.7.5",
)

Running the test gives me:

java.lang.IllegalArgumentException: Could not create type

	at net.bytebuddy.TypeCache.findOrInsert(TypeCache.java:140)
	at net.bytebuddy.TypeCache$WithInlineExpunction.findOrInsert(TypeCache.java:346)
	at net.bytebuddy.TypeCache.findOrInsert(TypeCache.java:161)
	at net.bytebuddy.TypeCache$WithInlineExpunction.findOrInsert(TypeCache.java:355)
	at org.spockframework.mock.runtime.ProxyBasedMockFactory$ByteBuddyMockFactory.createMock(ProxyBasedMockFactory.java:108)
	at org.spockframework.mock.runtime.ProxyBasedMockFactory.create(ProxyBasedMockFactory.java:65)
	at org.spockframework.mock.runtime.JavaMockFactory.createInternal(JavaMockFactory.java:59)
	at org.spockframework.mock.runtime.JavaMockFactory.create(JavaMockFactory.java:40)
	at org.spockframework.mock.runtime.CompositeMockFactory.create(CompositeMockFactory.java:44)
	at org.spockframework.lang.SpecInternals.createMock(SpecInternals.java:51)
	at org.spockframework.lang.SpecInternals.createMockImpl(SpecInternals.java:296)
	at org.spockframework.lang.SpecInternals.createMockImpl(SpecInternals.java:286)
	at org.spockframework.lang.SpecInternals.MockImpl(SpecInternals.java:105)
	at no.finn.travel.shared.common.kotlin.OpenTest.should be able to mock #subject(OpenTest.groovy:11)
Caused by: java.lang.IllegalStateException: Invisible parameter type of kotlin.jvm.internal.DefaultConstructorMarker arg2 for public no.finn.travel.shared.common.kotlin.SomeClass$SpockMock$bAkOnnH5(java.lang.String,int,kotlin.jvm.internal.DefaultConstructorMarker)
	at net.bytebuddy.dynamic.scaffold.InstrumentedType$Default.validated(InstrumentedType.java:925)
	at net.bytebuddy.dynamic.scaffold.MethodRegistry$Default.prepare(MethodRegistry.java:465)
	at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.make(SubclassDynamicTypeBuilder.java:162)
	at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.make(SubclassDynamicTypeBuilder.java:155)
	at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase.make(DynamicType.java:2639)
	at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Delegator.make(DynamicType.java:2741)
	at org.spockframework.mock.runtime.ProxyBasedMockFactory$ByteBuddyMockFactory$1.call(ProxyBasedMockFactory.java:113)
	at org.spockframework.mock.runtime.ProxyBasedMockFactory$ByteBuddyMockFactory$1.call(ProxyBasedMockFactory.java:110)
	at net.bytebuddy.TypeCache.findOrInsert(TypeCache.java:138)
	... 13 more

The test works without the byte-buddy dependency.

(ref. raphw/byte-buddy#350 )

@raphw
Copy link
Contributor

raphw commented Oct 3, 2017

Spock should configure Byte Buddy to run by new ByteBuddy().with(TypeValidation.DISABLED).

I will however look into the issue and hopefully fix it!

@henrik242
Copy link
Contributor Author

Project that demonstrates this: https://github.com/henrik242/kotlin-bytebuddy-spock

@henrik242
Copy link
Contributor Author

@leonard84 Would it be easy for you to just change to new ByteBuddy().with(TypeValidation.DISABLED) as @raphw suggests?

@raphw
Copy link
Contributor

raphw commented Oct 17, 2017

Sorry, little baby at home, I hope to look into this within this week. But yes, I suggest to turn off validation in the first place. Also, latest Byte Buddy fully supports Java 9, might be worth the update!

@leonard84
Copy link
Member

@raphw what are the implications of disabling type validation?

@raphw
Copy link
Contributor

raphw commented Oct 17, 2017

Byte Buddy will no longer run a manual assertion of the type's validity. This can result in an assertion error what Byte Buddy would prevent. As a background: when using Java agents, it is often better to fail during chaning a type rather then destroying it alltogether. For subclassing, destruction of a type that serves a purpose without a change is not possible. Of course, the manual validation can be too strict, which is why it makes sense to disable if failure is not crucial to a system like during test.

@leonard84
Copy link
Member

Is disabling the validation just a workaround until you fixed the underlying issue and should then be turned on again, or is it generally preferable to disable it for test code?

@raphw
Copy link
Contributor

raphw commented Oct 17, 2017

I generally recommend to disable it in production setups. If the instrumentation is set up correctlly, there is no good reason to use validation. But it can help a lot under development and be useful to fail fast under test.

@raphw
Copy link
Contributor

raphw commented Oct 21, 2017

I found out about the problem now and it is as a matter of fact a breach of the JVM spec by Kotlin. I have reported an issue on the tracker. The breach does not break the runtime as JVMs are sometimes less strict then the spec but there might be JVM implementations that are failing the check.

I recommend to disable validation as Byte Buddy validates against the formal spec to allow such border-line cases and rather cause a JVM failure. The way Byte Buddy is used in Spock already assures that no invalid code can be generated, therefore this should not be a problem.

@henrik242
Copy link
Contributor Author

@raphw Thanks for looking into this! So in order for this to work, spock needs to be updated? There's nothing you can do in bytebuddy?

BTW, can you link to the kotlin issue?

@raphw
Copy link
Contributor

raphw commented Oct 21, 2017

The issue is here: https://youtrack.jetbrains.com/issue/KT-20869

I could in theory disable the check in Byte Buddy's manual validation. Spock can opt out of this manual validation and I want to continue byte code against the specification rather then some quirky state as this can change rapidly.

@henrik242
Copy link
Contributor Author

How about a configurable whitelist

@henrik242
Copy link
Contributor Author

@leonard84 Thanks! Do you have any imminent plans of releasing a new Spock version?

@leonard84
Copy link
Member

@henrik242 sorry no, either use the SNAPSHOT or use jitpack.io for a stable-version.

@henrik242
Copy link
Contributor Author

@leonard84 No problem, I just built it myself

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

3 participants