Skip to content
Advertisement

How does the SharedSecrets mechanism work?

jdk.internal.misc.SharedSecrets describes itself as:

A repository of “shared secrets”, which are a mechanism for calling implementation-private methods in another package without using reflection. A package-private class implements a public interface and provides the ability to call package-private methods within that package; the object implementing that interface is provided through a third package to which access is restricted. This framework avoids the primary disadvantage of using reflection for this purpose, namely the loss of compile-time checking.

Can someone please provide an example that demonstrates how this mechanism enables classes in one package to access package-private methods in a different package?

Advertisement

Answer

Quoting http://blog.fuseyism.com/index.php/2008/05/26/sharing-secrets/:

When looking through OpenJDK for the VM project, I noticed that they have a rather interesting solution to this. This is encapsulated in sun.misc.SharedSecrets. This class provides access to instances of a number of public interfaces, such as sun.misc.JavaLangAccess. The actual implementations are provided as inner classes in the appropriate package e.g. java.lang, where it has access to the private and package-private variables and methods within.

Here is a concrete example:

  • We have two classes: Character and Story.
  • We want to expose Character‘s non-public methods to Story but not external users (classes residing outside the module).

Main.java:

JavaScript

Story.java

JavaScript

Character.java:

JavaScript

SharedSecrets.java:

JavaScript

SecretCharacter.java:

JavaScript

module-info.java:

JavaScript

Output

HARRY_POTTER enters the room and says: Your bird, there was nothing I could do. He just caught fire.

RON_WEASLEY enters the room and says: Who are you and what have you done with Hermione Granger?

HERMIONE_GRANGER enters the room and says: I’m not an owl!

Explanation

  • external.character.Character.getPhrase() is package-protected.
  • external.story.Story is located in a different package.
  • Normally Story wouldn’t be able to invoke Character.getPhrase(); however, SharedSecrets allows Character to share access with classes that it trusts.
  • Story invokes SharedSecrets.INSTANCE.secretCharacter which uses an anonymous nested class to access Character‘s internals.
  • external.story.Story can access internal.secrets.SharedSecrets because the two are located in the same module, but external users cannot access it because module-info.java does not export that package.

If you want to export SharedSecrets to trusted external modules, see https://stackoverflow.com/a/53653651/14731.

User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement