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

Allow non-vTable methods to be added/removed during class replacement #4872

Open
gacholio opened this issue Feb 25, 2019 · 10 comments
Open

Allow non-vTable methods to be added/removed during class replacement #4872

gacholio opened this issue Feb 25, 2019 · 10 comments

Comments

@gacholio
Copy link
Contributor

gacholio commented Feb 25, 2019

The addition or removal of methods which do not affect the shape of the vTable should be allowed in fast HCR.

Methods which never appear in the vTable are:

  • private instance methods
  • static methods

Methods which do not need to appear in the vTable but currently do:

  • final instance methods which do not override

New final methods should follow the invokeprivate path. This is likely a matter of removing their vTable modifier and modifying the restrictions on which methods can use invokeprivate during resolution.

@DanHeidinga
Copy link
Member

Related to #771

@gacholio
Copy link
Contributor Author

gacholio commented Mar 5, 2019

This will eventually require some JIT work to handle resolved methods which get deleted.

@gacholio
Copy link
Contributor Author

gacholio commented Mar 5, 2019

Experiments show that the the JVMTI can_maintain_original_method_order sorts the methods in the class according to the original class file (i.e. if the capability is acquired, and a redefinition reorders the methods in a class, the JVMTI GetClassMethods calls returns the original order [returns the same both before and after the reordering]).

It's not clear what this will mean in the presence of added and removed methods.

@gacholio
Copy link
Contributor Author

Some questions we need answered:

  • What happens to resolved methods which are deleted?

Obvious alternatives are: use placeholder method to throw, continue running the deleted method, re-resolve.

  • What happens to resolved methods which are added?

If a method is resolved, and a new method which would have been resolved is added, do we keep running the resolved method, or "correct" the invoke?

  • What does can_maintain_original_method_order mean in the presence of added/removed methods?

Perhaps if this capability is acquired, we cannot add/remove private.

Certainly not interested in trying to maintain ordering for deletion and re-addition of the same method.

  • Should there be a new JVMTI capability to control this?

Perhaps more than one, if we are to allow final/static.

  • Why does this apply only to private methods? Any method not impacting the vTable (static and possibly final) should be eligible.

@gacholio
Copy link
Contributor Author

Testing on Oracle openjdk10, the VM allows the addition (but not deletion) of private final methods.

Based on one testcase, the newly-added method does not cause re-resolution. The testcase is:

A public m()
B extends A
C extends B public m() { super.m() }

Where the super call targets A (not B as the compiler would generate).

The super call resolves to A.m(). If B is replaced adding "private final m()", the super call continues to run A.m(). If B.m() were present during resolution, it would be targetted.

@gacholio
Copy link
Contributor Author

gacholio commented Mar 19, 2019

Also, as expected, "resolve failed" state is not saved for method resolutions, which means that adding methods can cause previous failures to succeed the next time around.

A
B extends A
C extends B public m() { super.m() }

The super targets B in this case.

The super call fails with NoSuchMethodError (as it should). If B is replaced adding "private final m()", the super call then fails with IllegalAccessError, meaning the resolution was attempted again.

@gacholio
Copy link
Contributor Author

Also worth noting that the newly-added method breaks the ordering enforcement for can_maintain_original_method_order:

methods before:
	<init>()V
<end>
methods after:
	m()V
	<init>()V
<end>

So m() was not added to the end as would be expected.

@gacholio
Copy link
Contributor Author

Looks like the order of the new class file is obeyed in the addition case:

methods before:
	<init>()V
<end>
methods after:
	m2()V
	<init>()V
	m()V
<end>

@gacholio
Copy link
Contributor Author

-Xfuture has no effect on the ability to add private final methods.

@gacholio
Copy link
Contributor Author

Also verified Oracle only allows addition of:

  • private final instance methods
  • private static methods (final or not)

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

No branches or pull requests

2 participants