当前位置: 首页 > 知识库问答 >
问题:

通过varargs参数可能存在堆污染

柯奕
2023-03-14

我知道Java 7在使用泛型类型的varargs时会出现这种情况;

但我的问题是..

当Eclipse说“它的使用可能会潜在地污染堆”时,它到底是什么意思?

而且

新的@safevarargs注释如何防止这种情况发生?

共有2个答案

范志勇
2023-03-14

当你申报时

public static void foo(列表 ...bar) 编译器将其转换为

public static void foo(列表 []bar) 然后到

公共静态无效文件(list[]bar)

这样就会出现这样的危险:您会错误地将不正确的值分配到列表中,而编译器将不会触发任何错误。例如,如果T字符串,则以下代码将在编译时没有错误,但将在运行时失败:

// First, strip away the array type (arrays allow this kind of upcasting)
Object[] objectArray = bar;

// Next, insert an element with an incorrect type into the array
objectArray[0] = Arrays.asList(new Integer(42));

// Finally, try accessing the original array. A runtime error will occur
// (ClassCastException due to a casting from Integer to String)
T firstElement = bar[0].get(0);

如果您审阅了该方法以确保它不包含此类漏洞,那么您可以使用@safevarargs对其进行注释以抑制警告。对于接口,请使用@suppresswarnings(“unchecked”)

如果收到以下错误消息:

Varargs方法可能会导致堆污染,因为Varargs参数不可重构

并且您确信您的使用是安全的,那么您应该改用@suppresswarnings(“varargs”)。请参见@safeVarargs是此方法的适当注释吗?和https://stackoverflow.com/a/14252221/14731来解释第二种错误。

参考资料:

  • http://docs.oracle.com/javase/7/docs/technotes/guides/language/non-reiable-varargs.html
  • http://docs.oracle.com/javase/tutorial/java/generics/nonreifiablevarargstype.html#heap_pollution
颛孙和颂
2023-03-14

堆污染是一个专业术语。它引用具有不是它们所指向对象的超类型的类型的引用。

List<A> listOfAs = new ArrayList<>();
List<B> listOfBs = (List<B>)(Object)listOfAs; // points to a list of As

这可能导致“无法解释的”ClassCastException

// if the heap never gets polluted, this should never throw a CCE
B b = listOfBs.get(0); 

@safevarargs完全不阻止这一点。然而,有一些方法可以证明不会污染堆,编译器就是无法证明。以前,这类API的调用者会得到恼人的警告,这些警告完全没有意义,但必须在每个调用站点上加以抑制。现在API作者可以在声明站点将其抑制一次。

但是,如果该方法实际上并不安全,用户将不再受到警告。

 类似资料:
  • 问题内容: 我知道在Java 7中使用带有泛型类型的varargs时会发生这种情况。 但是我的问题是.. Eclipse说“使用它可能会污染堆”时,这到底是什么意思? 和 新注释如何防止这种情况? 问题答案: 堆污染是一个技术术语。它引用的引用类型不是其指向的对象的超类型。 这可能会导致“无法解释” 。 @SafeVarargs完全不能阻止这一点。但是,有些方法证明不会污染堆,编译器无法证明这一点

  • 此问题特定于将varargs与泛型一起使用: 为什么我会得到这个警告如果我像下面这样定义方法: 与此相反的是: 因此,在声明方法之前,我应该注意什么? 此问题类似于以下关于,但这些答案中显示的方案似乎不适用于: null null 这就是我试图污染堆的原因,但是每次错误的尝试都会导致而不是污染数组。 我使用的是Eclipse4.6.0和Java JDK8U74。

  • 问题内容: 我在JDK 1.8上将IntelliJ IDEA与javac一起使用。我有以下代码: IntelliJ IDEA不会在上面的代码中突出显示任何内容作为警告。但是,在编译时,以下行将显示在“消息”视图的“生成”选项卡中: 警告:(L,C)java:Varargs方法可能会导致不可修改的varargs参数varargs造成堆污染 注意#1:我已经指定了。 注意#2:指向作为参数传递给 假设

  • 描述 HTTP 参数污染,或者 HPP,在网站接受用户输入,将其用于生成发往其它系统的 HTTP 请求,并且不校验用户输出的时候发生。它以两种方式产生,通过服务器(后端)或者通过客户端。 在 StackExchange 上,SilverlightFox 提供了一个 HPP 服务端攻击的不错的例子。假设我们拥有以下站点:https://www.example.com/transferMoney.ph

  • 但是,如果Terminal中没有提供,我不知道如何(或者是否能够)为其设置默认值。像这样简单的东西不起作用。这里的一个解决方案是根据的内容或大小在函数中设置变量。但我不知道有没有更好的办法做到这一点。 因此,我正在寻找一种方法来使用来自终端的参数调用一个函数,其中需要一个数字(在本例中为2),而其余的是可选的,并设置为默认值。

  • 问题内容: 考虑方法声明: 该Object …参数只是对Objects 数组的引用。有没有办法在引用实际Object数组时使用此方法?如果我将Object数组传递给…参数-结果参数值将是一个二维数组-因为an Object[]本身就是an Object: 因此,数组的第一个组件(String.format方法中使用了哪个)将是一个数组,他将生成: 然后由于数组大小为1而发生错误。 该大胆的顺序是真