博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
通过varargs参数可能导致堆污染
阅读量:2378 次
发布时间:2019-05-10

本文共 4965 字,大约阅读时间需要 16 分钟。

本文翻译自:

I understand this occurs with Java 7 when using varargs with a generic type; 我知道在Java 7中使用带有泛型类型的varargs时会发生这种情况;

But my question is.. 但是我的问题是..

What exactly does Eclipse mean when it says "its use could potentially pollute the heap?" Eclipse说“使用它可能会污染堆”时,这到底是什么意思?

And

How does the new @SafeVarargs annotation prevent this? 新的@SafeVarargs注释如何防止这种情况?


#1楼

参考:


#2楼

@SafeVarargs does not prevent it from happening, however it mandates that the compiler is stricter when compiling code that uses it. @SafeVarargs不会阻止它的发生,但是它要求编译器在编译使用它的代码时要严格一些。

explains this in futher detail. 对此进行了更详细的说明。

Heap pollution is when you get a ClassCastException when doing an operation on a generic interface and it contains another type than declared. 堆污染是当您在通用接口上执行操作时收到ClassCastException时,它包含的类型不同于声明的类型。


#3楼

Heap pollution is a technical term. 堆污染是一个技术术语。 It refers to references which have a type that is not a supertype of the object they point to. 它引用的引用类型不是其指向的对象的超类型。

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

This can lead to "unexplainable" ClassCastException s. 这可能导致“无法解释的” ClassCastException

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

@SafeVarargs does not prevent this at all. @SafeVarargs完全不会阻止此操作。 However, there are methods which provably will not pollute the heap, the compiler just can't prove it. 但是,有些方法证明不会污染堆,编译器无法证明这一点。 Previously, callers of such APIs would get annoying warnings that were completely pointless but had to be suppressed at every call site. 以前,此类API的调用者会收到令人讨厌的警告,这些警告是完全没有意义的,但必须在每个调用站点中都加以抑制。 Now the API author can suppress it once at the declaration site. 现在,API作者可以在声明站点中取消一次它。

However, if the method actually is not safe, users will no longer be warned. 但是,如果方法实际上并不安全,用户将不再被警告。


#4楼

When you use varargs, it can result in the creation of an Object[] to hold the arguments. 使用varargs时,可能会导致创建Object[]来保存参数。

Due to escape analysis, the JIT can optimise away this array creation. 由于进行了转义分析,JIT可以优化此数组创建。 (One of the few times I have found it does so) Its not guaranteed to be optimised away, but I wouldn't worry about it unless you see its an issue in your memory profiler. (我发现它的少数几次)不能保证对其进行优化,但是除非您在内存事件探查器中看到它的问题,否则我不会担心。

AFAIK @SafeVarargs suppresses a warning by the compiler and doesn't change how the JIT behaves. AFAIK @SafeVarargs禁止编译器发出警告,并且不会更改JIT的行为。


#5楼

When you declare 当你声明

public static <T> void foo(List<T>... bar) the compiler converts it to public static <T> void foo(List<T>... bar)编译器将其转换为

public static <T> void foo(List<T>[] bar) then to public static <T> void foo(List<T>[] bar)然后

public static void foo(List[] bar)

The danger then arises that you'll mistakenly assign incorrect values into the list and the compiler will not trigger any error. 这样就有危险,您会错误地将错误的值分配给列表,并且编译器将不会触发任何错误。 For example, if T is a String then the following code will compile without error but will fail at runtime: 例如,如果T是一个String则以下代码将编译无错误,但在运行时将失败:

// 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 arrayobjectArray[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);

If you reviewed the method to ensure that it doesn't contain such vulnerabilities then you can annotate it with @SafeVarargs to suppress the warning. 如果您查看了该方法以确保它不包含此类漏洞,则可以使用@SafeVarargs进行注释,以禁止显示警告。 For interfaces, use @SuppressWarnings("unchecked") . 对于接口,请使用@SuppressWarnings("unchecked")

If you get this error message: 如果收到此错误消息:

Varargs method could cause heap pollution from non-reifiable varargs parameter Varargs方法可能会由于不可修正的varargs参数而导致堆污染

and you are sure that your usage is safe then you should use @SuppressWarnings("varargs") instead. 并且您确定自己的用法是安全的,那么应该@SuppressWarnings("varargs")使用@SuppressWarnings("varargs") See 请参见 and for a nice explanation of this second kind of error. 和以获得有关第二种错误的很好的解释。

References: 参考文献:


#6楼

The reason is because varargs give the option of being called with a non-parametrized object array. 原因是因为varargs提供了使用非参数化对象数组调用的选项。 So if your type was List < A > ... , it can also be called with List[] non-varargs type. 因此,如果您的类型是List <A> ...,则也可以使用List [] non-varargs类型调用它。

Here is an example: 这是一个例子:

public static void testCode(){    List[] b = new List[1];    test(b);}@SafeVarargspublic static void test(List... a){}

As you can see List[] b can contain any type of consumer, and yet this code compiles. 如您所见,List [] b可以包含任何类型的使用者,但是此代码可以编译。 If you use varargs, then you are fine, but if you use the method definition after type-erasure - void test(List[]) - then the compiler will not check the template parameter types. 如果使用varargs,就可以了,但是如果在类型擦除之后使用方法定义-void test(List [])-则编译器将不会检查模板参数类型。 @SafeVarargs will suppress this warning. @SafeVarargs将禁止显示此警告。

转载地址:http://xbexb.baihongyu.com/

你可能感兴趣的文章
spark streaming 写入hive表中文乱码
查看>>
Linux Cgroups概述
查看>>
centos7 硬盘性能测试
查看>>
cgroup使用--cpu资源限制
查看>>
cgroup使用--memory资源限制
查看>>
HBase与Hive整合
查看>>
Hbase架构简介
查看>>
mapreduce org.apache.hadoop.io.nativeio.NativeIO$Windows.access0(Ljava/lang/String;I)Z错误解决
查看>>
mapreduce中使用hadoop序列化
查看>>
Spark源代码阅读与调试环境搭建
查看>>
antlr4开发环境搭建
查看>>
mysql 5.7 忘记root密码
查看>>
mysql join实现算法
查看>>
spark sql原理---上篇
查看>>
hive四种排序order by,sort by,distribute by,cluster by的区别
查看>>
synchronized 使用方法与实现原理
查看>>
mysql 的那些常见连接方式
查看>>
java Atomic类使用
查看>>
spark RPC使用
查看>>
Comparable和Comparator有啥不一样
查看>>