当前位置: 首页 > 面试题库 >

SharedSecrets机制如何工作?

翟丰茂
2023-03-14
问题内容

jdk.internal.misc.SharedSecrets 描述为:

“共享秘密”的存储库,这是一种在不使用反射的情况下在另一个程序包中调用实现私有方法的机制。package-
private类实现了一个公共接口,并提供了在该包内调用package-
private方法的能力。实现该接口的对象是通过限制访问的第三包提供的。该框架避免了为此目的使用反射的主要缺点,即损失了编译时检查。

有人可以提供一个示例来说明此机制如何使一个包中的类访问另一个包中的包私有方法吗?


问题答案:

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

在通过OpenJDK查找VM项目时,我注意到他们对此有一个非常有趣的解决方案。它封装在sun.misc.SharedSecrets中。此类提供对许多公共接口实例的访问,例如sun.misc.JavaLangAccess。实际的实现作为相应包中的内部类提供,例如java.lang,在其中它可以访问其中的私有和私有包变量及方法。

这是一个具体的例子:

  • 我们有两个类:CharacterStory
  • 我们想向外部用户(而不是模块外部的类)公开Character的非公共方法Story

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;
}

输出量

HARRY_POTTER进入房间说:您的鸟儿,我无能为力。他只是着火了。

RON_WEASLEY进入房间说:你是谁,你对Hermione Granger做过什么?

HERMIONE_GRANGER进入房间并说:我不是猫头鹰!

说明

  • external.character.Character.getPhrase() 受包装保护。
  • external.story.Story 位于不同的程序包中。
  • 通常Story无法调用Character.getPhrase(); 但是,SharedSecrets允许Character与其信任的类共享访问权限。
  • Story调用SharedSecrets.INSTANCE.secretCharacter,该调用使用匿名嵌套类访问Character的内部。
  • external.story.Story可以访问,internal.secrets.SharedSecrets因为两者位于同一模块中,但是外部用户无法访问它,因为module-info.java不导出该程序包。


 类似资料:
  • 问题内容: 我想创建一个发布-订阅基础结构,其中每个订阅者都将收听多个(例如100k)频道。 我认为可以将Redis PubSub用于此目的,但是我不确定在这里订阅数千个频道是否是最佳实践。为了回答这个问题,我想知道Redis中的订阅机制在后台如何工作。 另一种选择是为每个订户创建一个频道,并在两者之间放置一些组件,该组件将获取所有消息并将其发布到相关的频道。 还有其他想法吗? 问题答案: Sal

  • 所以我以前遇到过这个问题,很自然地我在这里寻求帮助。Luksprog的回答很棒,因为我不知道ListView和GridView是如何通过回收视图来优化自己的。所以在他的建议下,我能够改变我向GridView添加视图的方式。问题是现在我有了一些没有意义的东西。这是我的来自我的: 问题是当我滚动时,这会发生,而不是在位置0上。。。看起来像是第6位和第8位,加上第8位有两个。现在我仍在尝试使用ListV

  • 问题内容: 我的问题与使反应挂钩成为可能的Javascript机制有关。 React的最新发展使我们能够创建钩子。对于React状态,在以下简单函数中: 挂钩返回带有访问器和变量的数组,我们通过App函数内部的数组分解来使用它们。 因此,在幕后,该钩子看起来像(只是一个伪代码): 当您在JS中尝试此方法时,它将无法正常工作- 如果您在某处使用,从数组分解的值将不会更新。即使您将用作对象,也不能使用

  • 本文向大家介绍spark工作机制?相关面试题,主要包含被问及spark工作机制?时的应答技巧和注意事项,需要的朋友参考一下 用户在client端提交作业后,会由Driver运行main方法并创建spark context上下文。 执行add算子,形成dag图输入dagscheduler,按照add之间的依赖关系划分stage输入task scheduler。 task scheduler会将sta

  • 问题内容: 似乎该包中的和类已在Java 9中删除。 Java 9中是否可以替代这些类提供的功能? 问题答案: 以上两个类都打包在包中。 您可以尝试访问它们的一种方法是使用选项 对于您的用例为: 注意 : -JEP-261:模块系统的 免责声明- 该和选择必须非常小心使用。您可以使用它们来访问库模块的内部API,甚至可以访问JDK本身,但这需要您自担风险: 如果更改或删除了该内部API,则库或应用

  • 本文向大家介绍Flume工作机制是什么?相关面试题,主要包含被问及Flume工作机制是什么?时的应答技巧和注意事项,需要的朋友参考一下 核心概念是agent,里面包括source、chanel和sink三个组件。 source运行在日志收集节点进行日志采集,之后临时存储在chanel中,sink负责将chanel中的数据发送到目的地。 只有成功发送之后chanel中的数据才会被删除。 首先书写fl