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

Error with setInternalState and JDK12 "java.lang.NoSuchFieldException: modifiers" #939

Closed
eolivelli opened this issue Oct 3, 2018 · 10 comments · Fixed by #1010
Closed
Labels

Comments

@eolivelli
Copy link
Contributor

What steps will reproduce the problem?
Use WhiteBox#setInternalState with JDK12

What is the expected output?
setInternalState does not throw exception

What do you see instead?

java.lang.RuntimeException: Internal error: Failed to find the "modifiers" field in method setInternalState.
	at org.powermock.reflect.internal.WhiteboxImpl.sedModifiersToField(WhiteboxImpl.java:2354)
	at org.powermock.reflect.internal.WhiteboxImpl.removeFinalModifierIfPresent(WhiteboxImpl.java:2318)
	at org.powermock.reflect.internal.WhiteboxImpl.setField(WhiteboxImpl.java:2304)
	at org.powermock.reflect.internal.WhiteboxImpl.setInternalState(WhiteboxImpl.java:304)
	at org.powermock.reflect.internal.WhiteboxImpl.setInternalState(WhiteboxImpl.java:317)
	at org.powermock.reflect.Whitebox.setInternalState(Whitebox.java:190)
	at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:61)
	at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:365)
	at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:273)
	at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:238)
	at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:159)

What version of the product are you using?
2.0.0.Beta5

@eolivelli
Copy link
Contributor Author

Anyone else has this problem ?
Is there any workaround ?

@ijuma
Copy link
Contributor

ijuma commented Nov 7, 2018

@eolivelli
Copy link
Contributor Author

eolivelli commented Nov 7, 2018

Thank you @ijuma for posting my discussion.
I will try the approach suggested by Alan.
If it is interesting I can share my trials woth powermock community.
It is blocker for me for jdk12 adoption

@eolivelli
Copy link
Contributor Author

eolivelli commented Nov 8, 2018

@ijuma this is my proof of concept, it is a very simple agent made with ByteBuddy.
https://github.com/eolivelli/tweakjava

It works for most of the cases, but in the case he specific error at at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:61)

It does not work because ByteBuddy is not "transforming" the Annotation[] fAnnotations field of org.junit.runner.Description.

It seems a bug in ByteBuddy (raphw/byte-buddy#559).

That specific case, could be worked-around in PowerMock by just not failing in case of failure in that point in the finally block. In that case there is a best-effort trial to reset a field in description.

Temporary you can bypass the specific error with a subclass of PowerMockRunner, this is very hacky but 'it works'

public class SafePowerMockRunner extends PowerMockRunner {

    public SafePowerMockRunner(Class<?> klass) throws Exception {
        super(klass);
    }

    @Override
    public void run(RunNotifier notifier) {
        try {
            super.run(notifier);
        } catch (RuntimeException err) {
            if (err.getCause() instanceof java.lang.NoSuchFieldException
                    && err.getCause().getMessage().equals("modifiers")) {
                // on JDK12 you cannot change 'modifiers'
            } else {
                throw err;
            }
        }
    }

}

@eolivelli
Copy link
Contributor Author

For org.powermock.modules.junit4.PowerMockRunner I think we should have a minimal fix which ignores the error. I can send a patch

@eolivelli
Copy link
Contributor Author

This is my minimal patch
#955

@rnveach
Copy link

rnveach commented Apr 21, 2019

Fix in PR only suppresses exception in one part of powermock's own code but if users call Whitebox.setInternalState on a final field themselves they will still get the exception.
There is no alternative way to accomplish this task when using Java 12?

@eolivelli
Copy link
Contributor Author

@rnveach you can use a java agent like this one https://github.com/eolivelli/tweakjava

@ghost
Copy link

ghost commented May 10, 2019

Unsafe.putObject(base, offset, value) works fine under Java 12.

@Vampire
Copy link
Contributor

Vampire commented Sep 11, 2019

There are multiple ways.
There are a bunch of classes for which fields are filtered now when using Class#getDeclaredFields.

  • But you can either use yet another private API and use the method Class#getDeclaredFields0(false) to get the unfiltered list and pick the wanted field from there,
  • Or you can use Unsafe.putObject
  • Or you can use VarHandles and MethodHandles.privateLookupIn()
    The latter probably being the most "appropriate" to do unappropriate things, as it is the only official API.

odl-github pushed a commit to opendaylight/odlparent that referenced this issue Oct 22, 2019
No official release notes (yet?), the following issues are fixed:
powermock/powermock#685
powermock/powermock#992
powermock/powermock#939

Change-Id: Ie8266a961c75cb0dcb606e4639ef0b91a8992b5e
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
odl-github pushed a commit to opendaylight/odlparent that referenced this issue Oct 23, 2019
No official release notes (yet?), the following issues are fixed:
powermock/powermock#685
powermock/powermock#992
powermock/powermock#939

Change-Id: Ie8266a961c75cb0dcb606e4639ef0b91a8992b5e
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
(cherry picked from commit 3479902)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
PowerMock 2.x
  
To Do
Development

Successfully merging a pull request may close this issue.

5 participants