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

@AutoClose cannot invoke methods due to strict encapsulation with the module system #3684

Closed
bjmi opened this issue Feb 8, 2024 · 4 comments

Comments

@bjmi
Copy link
Contributor

bjmi commented Feb 8, 2024

Running following test

class AutoCloseTest {
    @AutoClose
    InputStream inputStream = InputStream.nullInputStream();

    @AutoClose("shutdown")
    ExecutorService service = Executors.newSingleThreadExecutor();

    @Test
    void test() { }
}

results in:

java.lang.reflect.InaccessibleObjectException: Unable to make public void java.io.InputStream$1.close() throws java.io.IOException accessible: module java.base does not "opens java.io" to unnamed module @cc43f62
java.lang.reflect.InaccessibleObjectException: Unable to make public void java.util.concurrent.Executors$AutoShutdownDelegatedExecutorService.shutdown() accessible: module java.base does not "opens java.util.concurrent" to unnamed module @cc43f62

In a nutshell

InputStream.class.getMethod("close").invoke(inputStream);      // works
inputStream.getClass().getMethod("close").invoke(inputStream); // fails java.lang.IllegalAccessException: class AutoCloseTest cannot access a member of class java.io.InputStream$1 (in module java.base) with modifiers "public"

Some research revealed:

I have to walk the interfaces + subclasses then to find a method that works.

OpenJDK 21.0.2 for Windows
JUnit 5.11.0-SNAPSHOT

@sbrannen
Copy link
Member

sbrannen commented Feb 8, 2024

Thanks for bringing this to our attention, @bjmi! 👍

I'm very familiar with Spring's ClassUtils.getInterfaceMethodIfPossible() approach. We introduced that to be compatible with the Java Module System.

So, it looks like we probably need that in JUnit as well.

I'll look into it!

@sbrannen sbrannen self-assigned this Feb 8, 2024
@sbrannen sbrannen added this to the 5.11 M1 milestone Feb 8, 2024
@sbrannen sbrannen changed the title @AutoClose struggles with inaccessible methods @AutoClose cannot invoke inaccessible methods Feb 8, 2024
@sbrannen sbrannen changed the title @AutoClose cannot invoke inaccessible methods @AutoClose cannot invoke methods due to strict encapsulation with the module system Feb 8, 2024
@sbrannen sbrannen removed this from the 5.11 M1 milestone Feb 9, 2024
@sbrannen
Copy link
Member

sbrannen commented Feb 9, 2024

Please note that I have removed the milestone assignment since @AutoClose has not yet been released.

@bjmi
Copy link
Contributor Author

bjmi commented Feb 12, 2024

Just one consideration: is it sufficient to only search for a corresponding interface method?

Abstract base classes e.g. java.io.InputStream (< Java 1.5), java.nio.Buffer, or java.util.ResourceBundle function in a similar way to interfaces.

Shouldn't they also be supported?

@sbrannen
Copy link
Member

Hi @bjmi,

That's a valid question, so thanks for bringing it up.

I suppose that one might ideally want to find the first matching method which is declared in a public type (for example, a class, abstract class, or interface).

However, my primary goal was to support the most common use cases for @AutoClose methods which are likely one of the following.

  • AutoCloseable#close
  • a method defined in a public interface which may potentially reside in a different module
  • a method defined in the same module as the test class (or in a module that has opened itself up for reflection to the test's module) which may be invoked via reflection

In that regard, I think we have the major use cases covered currently.

However, if people start complaining about JUnit not being able to invoke @AutoClose methods on private types in different modules where the method is actually publicly defined in a public superclass, we may consider enhancing the method search/invocation algorithm.

Cheers,

Sam

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