How does the SharedSecrets mechanism work?

后端 未结 1 1494
傲寒
傲寒 2021-01-03 15:55

jdk.internal.misc.SharedSecrets describes itself as:

A repository of \"shared secrets\", which are a mechanism for calling implemen

相关标签:
1条回答
  • 2021-01-03 16:24

    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:

    package external.main;
    
    import external.character.Character;
    import external.story.Story;
    
    public class Main
    {
        public static void main(String[] args)
        {
            Story story = new Story();
            story.introduce(Character.HARRY_POTTER);
            story.introduce(Character.RON_WEASLEY);
            story.introduce(Character.HERMIONE_GRANGER);
        }
    }
    

    Story.java

    package external.story;
    
    import external.character.Character;
    import internal.secrets.SharedSecrets;
    
    public final class Story
    {
        /**
         * Introduces a character.
         *
         * @param character the character
         */
        public void introduce(Character character)
        {
            System.out.println(character.name() + " enters the room and says: " + SharedSecrets.INSTANCE.secretCharacter.getPhrase(character));
        }
    }
    

    Character.java:

    package external.character;
    
    import internal.secrets.SecretCharacter;
    import internal.secrets.SharedSecrets;
    
    public enum Character
    {
        HARRY_POTTER
        {
            @Override
            String getPhrase()
            {
                return "Your bird, there was nothing I could do. He just caught fire.";
            }
        },
        RON_WEASLEY
        {
            @Override
            String getPhrase()
            {
                return "Who are you and what have you done with Hermione Granger?";
            }
        },
        HERMIONE_GRANGER
        {
            @Override
            String getPhrase()
            {
                return "I'm not an owl!";
            }
        };
    
        static
        {
            SharedSecrets.INSTANCE.secretCharacter = new SecretCharacter()
            {
                @Override
                public String getPhrase(Character character)
                {
                    return character.getPhrase();
                }
            };
        }
    
        /**
         * @return the character's introductory phrase
         */
        abstract String getPhrase();
    }
    

    SharedSecrets.java:

    package internal.secrets;
    
    public final class SharedSecrets
    {
        public static SharedSecrets INSTANCE = new SharedSecrets();
        public SecretCharacter secretCharacter;
    
        /**
         * Prevent construction.
         */
        private SharedSecrets()
        {
        }
    }
    

    SecretCharacter.java:

    package internal.secrets;
    
    import external.character.Character;
    
    public interface SecretCharacter
    {
        /**
         * @param character a character
         * @return the character's introductory phrase
         */
        String getPhrase(Character character);
    }
    

    module-info.java:

    module SharedSecret
    {
        exports external.character;
        exports external.main;
        exports external.story;
    }
    

    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.

    0 讨论(0)
提交回复
热议问题