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

Serialization object construction doesn't work on JDK9 anymore #45

Closed
ropalka opened this issue Oct 28, 2016 · 14 comments
Closed

Serialization object construction doesn't work on JDK9 anymore #45

ropalka opened this issue Oct 28, 2016 · 14 comments
Milestone

Comments

@ropalka
Copy link

ropalka commented Oct 28, 2016

There was an incompatible change introduced in method
sun.reflect.ReflectionFactory.newConstructorForSerialization()
in recent JDK9 b142 build.

@henri-tremblay
Copy link
Contributor

I noticed that indeed UnsafeFactoryInstantiator and Objenesis in general are working for standard instantiation. However, serialization isn't working anymore since ObjectStreamClassInstantiator isn't working anymore. Let's fix that.

@henri-tremblay henri-tremblay changed the title UnsafeFactoryInstantiator doesn't work on JDK9 anymore Serialization object construction doesn't work on JDK9 anymore Jan 12, 2017
@henri-tremblay henri-tremblay added this to the 2.5 milestone Jan 13, 2017
@johnou
Copy link

johnou commented Feb 26, 2017

@henri-tremblay have you tested SunReflectionFactorySerializationInstantiator with JDK9? I was under the impression that calling setAccessible(true) fails on Java 9. See mp911de/lettuce@a3c36bc .

@henri-tremblay
Copy link
Contributor

I did. And it was working. You have a different experience? Do you have a test case?

@johnou
Copy link

johnou commented Mar 1, 2017

@mp911de I'm having trouble getting my hands on the latest EA actually..

jdk9

@johnou
Copy link

johnou commented Mar 1, 2017

@mp911de could I trouble you for a bit more information about the commit I referenced above?

@mp911de
Copy link

mp911de commented Mar 1, 2017

@johnou sure (mail, gitter, Twitter, …). setAccessible(true) fails for encapsulated elements. That's the Java 8 code path. A different path

MethodHandles.lookup().findSpecial(method.getDeclaringClass(), method.getName(), MethodType.methodType(method.getReturnType(), method.getParameterTypes()), method.getDeclaringClass());

works for Java 9 (but not Java 8 and earlier). It's however possible this might change in future Java 9 versions because "the team is fixing loopholes until the Java 9 release" (statement from an Oracle PM I met recently).

@johnou
Copy link

johnou commented Mar 1, 2017

@mp911de that's perfect, just wanted to give @henri-tremblay a heads up.

@mp911de
Copy link

mp911de commented Mar 1, 2017

Shoot! The code from above works inside of unnamed modules but not if you create a real Java 9 module and import the library that's going to invoke a default method on an interface. I found an ugly hack via a derived class. It boils down back to where we started: there's no official way to deal with Methodhandles of encapsulated components.

@henri-tremblay
Copy link
Contributor

What do you mean by "encapsulated components"? And then it's getting annoying to test... I fell like I should just use the UnsafeInstantiator and it will be then end of it.

@mp911de
Copy link

mp911de commented Mar 2, 2017

I'm still new to the Java 9 terminology so sorry if I don't use the right terms, still learning. I mean by that a Java 9 module with a module descriptor.

@henri-tremblay
Copy link
Contributor

Thanks... I'm not that good with the terminology either.

So can you please confirm the current state:
1- I'm in module A which is importing module B
2- I want to create an instance of a class in module B
3- setAccessible fails

Is that it?

@mp911de
Copy link

mp911de commented Mar 2, 2017

setAccessible fails if the source module does not export/opens the package to the framework library.

setAccessible(true) on a module's member fails when called in a framework if:

module com.my.module {

}

setAccessible(true) on a module's member works when called in a framework if:

module com.my.module {

	opens com.my.package to org.framework.module;
	// or 
	//exports com.my.package to org.framework.module;
}

I received, however, a response to private MethodHandle lookup yesterday, see http://mail.openjdk.java.net/pipermail/core-libs-dev/2017-March/046567.html

@henri-tremblay
Copy link
Contributor

Oh dear Lord... First time I see "open". So, again, to make sure I get it. Let's say I have:

  • com.mycompany module. It imports org.springframework
  • org.springframework module that is calling Objenesis to create a proxy. It imports org.objenesis
  • org.objenesis module

And then org.springframework tries to create a proxy using org.objenesis to create an instance of a class from com.mycompany.

This will fail unless com.mycompany is defined like this:

module com.my.module {
	opens com.mycompany to org.objenesis;
}

Is that right?

@mp911de
Copy link

mp911de commented Mar 2, 2017

I can confirm that's what you need to do for plain old jars. I'm not sure whether that's still the case when each module comes with a module descriptor and declares its dependencies. I attached a screenshot that shows a Maven and a module-info.java to make a plain old jar working with a Java 9 module. /cc @nicolaiparlog

screenshot 2017-03-01 20 38 28

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

4 participants