Я думаю, что ответ в том, что JDK 1.5 игнорирует установку размера стека по умолчанию на определенное значение. Скажем, если у вас размер стека по умолчанию 512 КБ и (вы верите в это) вы установили его на 256 КБ, в конечном итоге он все равно будет иметь значение 512 КБ. В JDK 6 вы также устанавливаете размер по умолчанию 256 КБ, но здесь он действительно будет иметь это значение. Это может быть причиной того, что ваша Windows 7 получает ошибку (ранее)!
Посмотрите на эту таблицу -Xss по умолчанию:
Platform Default
----------------------------------
Windows IA32 64 KB
Linux IA32 128 KB
Windows x86_64 128 KB
Linux x86_64 256 KB
Windows IA64 320 KB
Linux IA64 1024 KB (1 MB)
Solaris Sparc 512 KB
Здесь вы можете видеть, что значения по умолчанию различаются в зависимости от платформы, на которой вы работаете.
См.: http://docs.oracle.com/cd/E13150_01/jrockit_jvm/jrockit/jrdocs/refman/optionX.html#wp1024112
Кроме того, поскольку вы получаете StackOverflowError
в одной системе, но не в другой, 32-разрядная виртуальная машина будет хранить адреса в 4 байтах памяти. 64-битная виртуальная машина будет хранить то же самое с 8 байтами! Итак, если вы установите значение размера стека в 256 КБ (да, это килобайты), 32-разрядная система (вероятно, ваша система XP) может хранить 65 536 адресов в своей памяти стека. 64-битная система (ваша система Windows 7) может хранить только 32 768 адресов. Это может быть проблемой между этими двумя системами.
Как правило, Java объекты потребляют тот же объем памяти в 32-разрядной виртуальной машине, что и в 64-разрядной ВМ. Очевидно, что если у вас есть Object
, который ссылается на 100 других Object
, это увеличит размер основного Object
на 400 байт на 64-битной JVM.
Дополнительно сказано:
Обратите внимание, что в некоторых версиях Windows ОС может округлять размеры стека потоков, используя очень грубую гранулярность. Если запрошенный размер меньше размера по умолчанию на 1 КБ или более, размер стека округляется до значения по умолчанию; в противном случае размер стека округляется до числа, кратного 1 МБ.
64 КБ — это наименьшее количество пространства стека, разрешенное для каждого потока.
См.: http://www.oracle.com/technetwork/java/hotspotfaq-138619.html#threads_oom
К сожалению, я не нашел конкретного объяснения, как выражается грубая детализация.
Попробуйте запустить следующий пример программы на обеих платформах, чтобы угадать, насколько размеры стеков различаются между собой:
public class StackOverflowTest {
public static void main(String[] args) {
recurse(0);
}
private static void recurse(int i) {
try {
recurse(++i);
} catch (StackOverflowError e) {
System.out.println(i);
System.exit(0);
}
}
}
Результаты на моей машине:
Windows 7 (64-bit)
Stack calls Java Stack size
------------------------------------------
11424 JDK 5 64-bit default
11424 JDK 5 64-bit -Xss256K
11424 JDK 5 64-bit -Xss1024K
6260 JRE 6 32-bit default
4894 JRE 6 32-bit -Xss256K
35405 JRE 6 32-bit -Xss1024K
10448 to 10468 JDK 7 64-bit default
2255 to 2274 JDK 7 64-bit -Xss256K
10448 to 10468 JDK 7 64-bit -Xss1024K
10396 to 41894 JDK 8 64-bit default
2203 to 4590 JDK 8 64-bit -Xss256K
10396 to 41894 JDK 8 64-bit -Xss1024K
(Было бы здорово, если бы список можно было расширить за счет других систем, на которых вы работаете!)
Как видите, размеры стеков — полная загадка. Это может быть связано с тем, что разные версии Java занимают разное место в памяти стека.
Кроме того, если вы установите размер стека с помощью -Xss
, значение будет игнорироваться в выпуске Java 5.
С JDK 7 вы не всегда получаете тот же результат, что и в других выпусках. То же самое касается JDK 8, где диапазоны существенно различаются.
Возможно, вы сами разберетесь, отличается ли он лишь незначительно или нет на ваших собственных системах.
Дополнительная литература: http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html#jvms-2.5.2
Эта спецификация позволяет стекам виртуальной машины Java быть либо фиксированного размера, либо динамически расширяться и сжиматься в соответствии с требованиями вычислений. Если стеки виртуальной машины Java имеют фиксированный размер, размер каждого стека виртуальной машины Java может быть выбран независимо при создании этого стека.
Итак, вопрос в том, что подразумевается под динамически расширяться?
Затем я обнаружил ошибку в исходниках, которая может представлять интерес, если вы используете более раннюю версию Java 6:
http://bugs.java.com/view_bug.do?bug_id=6316197
person
Community
schedule
28.01.2014