[英]Large size of HashSet throwing StackOverflow Error
我有 81K 長 object 記錄,我正在嘗試將其存儲在 HashSet 中。 我的代碼片段如下所示:
private static HashSet<Long> hashSet = new HashSet<>(Arrays.asList(*81K records*));
編譯時給了我StackOverflow Error
。 我不明白為什么這里只有 81K 記錄有問題? 解決方案表示贊賞。
Java 版本。 :
openjdk version "1.8.0_322"
OpenJDK Runtime Environment Corretto-8.322.06.1 (build 1.8.0_322-b06)
OpenJDK 64-Bit Server VM Corretto-8.322.06.1 (build 25.322-b06, mixed mode)
堆棧跟蹤:
[javac]
[javac]
[javac] The system is out of resources.
[javac] Consult the following stack trace for details.
[javac] java.lang.StackOverflowError
[javac] at com.sun.tools.javac.code.Type.map(Type.java:220)
[javac] at com.sun.tools.javac.code.Type.map(Type.java:220)
[javac] at com.sun.tools.javac.code.Type.map(Type.java:220)
[javac] at com.sun.tools.javac.code.Type.map(Type.java:220)
[javac] at com.sun.tools.javac.code.Type.map(Type.java:220)
[javac] at com.sun.tools.javac.code.Type.map(Type.java:220)
[javac] at com.sun.tools.javac.code.Type.map(Type.java:220)
[javac] at com.sun.tools.javac.code.Type.map(Type.java:220)
[javac] at com.sun.tools.javac.code.Type.map(Type.java:220)
[javac] at com.sun.tools.javac.code.Type.map(Type.java:220)
[javac] at com.sun.tools.javac.code.Type.map(Type.java:220)
[javac] at com.sun.tools.javac.code.Type.map(Type.java:220)
[javac] at com.sun.tools.javac.code.Type.map(Type.java:220)
[javac] at com.sun.tools.javac.code.Type.map(Type.java:220)
[javac] at com.sun.tools.javac.code.Type.map(Type.java:220)
[javac] at com.sun.tools.javac.code.Type.map(Type.java:220)
[javac] at com.sun.tools.javac.code.Type.map(Type.java:220)
[javac] at com.sun.tools.javac.code.Type.map(Type.java:220)
[javac] at com.sun.tools.javac.code.Type.map(Type.java:220)
[javac] at com.sun.tools.javac.code.Type.map(Type.java:220)
[javac] at com.sun.tools.javac.code.Type.map(Type.java:220)
[javac] at com.sun.tools.javac.code.Type.map(Type.java:220)
Type
的第 220 行:
208 /**
209 * Return the least specific subtype of t that starts with symbol
210 * sym. If none exists, return null. The least specific subtype
211 * is determined as follows:
212 *
213 * <p>If there is exactly one parameterized instance of sym that is a
214 * subtype of t, that parameterized instance is returned.<br>
215 * Otherwise, if the plain type or raw type `sym' is a subtype of
216 * type t, the type `sym' itself is returned. Otherwise, null is
217 * returned.
218 */
219 public Type asSub(Type t, Symbol sym) {
220 return asSub.visit(t, sym);
221 }
222 // where
223 private final SimpleVisitor<Type,Symbol> asSub = new SimpleVisitor<Type,Symbol>() {
The specific issue is that Java type inference cannot deal with such a long constant -- as reflected by the stack overflow you got in the Java compiler itself -- but it's also the case that Java bytecode format does not allow you to put such large amounts數據到您的源代碼。 方法代碼的最大大小——這是 Java 在幕后初始化它的方式——是 64KB; 單獨存儲 81K long
常量是這個限制的 10 倍。
您當然可以將此數據存儲到HashSet
等中,但您必須在運行時從文件中加載它。
HashSet
在這里無關緊要。 有問題的部分是具有 81,000 個元素的Arrays.asList
的可變參數調用。
要重現該問題,我們可以使用以下代碼
class Tmp {
static final String ARGUMENTS = "<<INSERT ARGUMENTS HERE>>";
static final List<String> TEMPLATE = Arrays.asList(
"import java.util.Arrays;",
"import java.util.List;",
"",
"class Tmp {",
" static final List<Integer> L = Arrays.asList(",
ARGUMENTS,
" );",
"}");
public static void main(String[] args) throws IOException {
Path p = Files.createTempFile("Test", ".java");
Files.write(p, () -> TEMPLATE.stream()
.flatMap(line -> line.equals(ARGUMENTS)? varargsArgument(): Stream.of(line))
.iterator());
JavaCompiler c = ToolProvider.getSystemJavaCompiler();
c.run(System.in, System.out, System.err, p.toString());
}
static Stream<CharSequence> varargsArgument() {
return IntStream.range(0, 8100).mapToObj(i -> IntStream.range(0, 10)
.mapToObj(j -> i * 10 + j + (i < 8099 || j < 9? ", ": ""))
.collect(Collectors.joining()));
}
}
使用OpenJDK 8 ,它產生
java.lang.StackOverflowError
at com.sun.tools.javac.code.Type.map(Type.java:220)
…
在最近的 JDK 上,例如JDK 12 ,它產生
/tmp/Test14992292170362927520.java:6: error: code too large
static final List<Integer> L = Arrays.asList(
^
表明即使編譯器錯誤已修復,此類代碼也無法編譯。
此類數據量應作為嵌入式資源包含在內,您在啟動時讀取一次。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.