45

考虑这个例子:

import java.lang.reflect.Field;

public class Test {

    public static void main(String[] args) {
        C c = new C();
        try {
            Field f = C.class.getDeclaredField("a");
            f.setAccessible(true);
            Integer i = (Integer)f.get(c);
            System.out.println(i);
        } catch (Exception e) {}
    }
}

class C {
    private Integer a =6;
}

允许您通过反射访问类的私有字段似乎不合逻辑。为什么会有这样的功能?允许这样的访问不是“危险的”吗?

4

7 回答 7

60

Private 旨在防止意外误用,而不是作为一种安全机制。如果您选择绕过它,那么您可以自行承担风险并假设您知道自己在做什么。

于 2009-08-06T15:29:33.503 回答
22

两者getDeclaredField()setAccessible()实际上都由安全管理器检查,并且当您的代码不允许这样做时会抛出异常。您通常不会注意到它,因为 Java 代码通常在没有安全管理器的情况下运行。

一个重要的例外是小程序,它总是与安全管理器一起运行。

于 2009-08-06T15:20:19.870 回答
10

是的,它不是很好,但它确实允许 Java 序列化等框架工作。

在反射对象中设置可访问标志允许具有足够特权的复杂应用程序(例如 Java 对象序列化或其他持久性机制)以通常被禁止的方式操作对象。

我相信该功能可以通过SecurityManager

http://javabeans.asia/2008/10/12/how_to_set_securitymanager_and_java_security_policy_programmatically.html

于 2009-08-06T15:18:14.880 回答
8

反射是危险的。时期。

为了稍微提高安全性而限制真正危险系统的实用性有什么意义?

此外,自动序列化需要能够从任何类中“吸脑”;在这种情况下,忽略访问修饰符是必要的。

于 2009-08-06T15:16:58.987 回答
4

来自:http: //java.sun.com/docs/books/tutorial/reflect/

反射通常由需要能够检查或修改在 Java 虚拟机中运行的应用程序的运行时行为的程序使用。

它是一种工具,可以让人们打破一些规则,可以把它扔到脚上或正确使用它。

于 2009-08-06T15:17:51.403 回答
4

反射是一个用于进入类的完整 API。私人会员和所有。

如果您不信任正在运行的代码(小程序等),您可以完全阻止代码使用反射。有关详细信息,请参阅此 Stack Overflow 问题

于 2009-08-06T15:22:03.673 回答
3

从包的描述java.lang.reflect

这个包中的类,以及 java.lang.Class调试器、解释器、对象检查器、类浏览器等应用程序以及需要访问目标对象的公共成员(基于其运行时类)或给定类声明的成员。

反射提供了一种通过类和对象之间的常规交互通常无法获得的方法来访问有关类的信息的机制。其中之一是允许从外部类和对象访问私有字段。

是的,一般来说反射确实很危险,因为它可以暴露类和对象的内部。

然而,它也是一个非常强大的工具,可以用来检查类和对象的内部,这是其他标准方法无法访问的。

于 2009-08-06T15:18:08.780 回答