У меня есть обычная 64-битная JVM с точкой доступа, размер стека которой составляет 1 МБ. Теперь я пытался сериализовать объект, который имеет иерархию из 3022 родителей, и это дает мне исключение SO (ирония).
Вот код:
while(epc.getParent()!=null){
epc=epc.getParent();
count++;
}
print(count);//3022
Приведенный выше код предназначен только для указания иерархии, но настоящая проблема возникает, когда я пытаюсь сериализовать объект epc
в ObjectOutputStream.
Вопрос: что указывает размер стека 1 МБ в JVM, поскольку я понятия не имею, какой размер кадра стека? Я уверен, что это не 1 КБ на кадр стека, потому что я успешно выполнил код на -Xss3000k.
Еще один вопрос: будет ли каждый поток иметь размер стека 3000k, если я поставлю параметр JVM -Xss3000k?
2 ответа
Вопрос: что указывает размер стека 1 МБ в JVM, поскольку я понятия не имею, какой размер кадра стека?
Размер стека потока по умолчанию 1 МБ означает, что каждый поток имеет 1 МБ (1048576 байт) пространства стека ... по умолчанию. Исключением является ситуация, когда ваш код создает поток с помощью одного из конструкторов Thread
, где вы можете указать аргумент размера стека.
Размер кадра стека зависит от вызываемого метода. Он должен содержать параметры метода и локальные переменные, поэтому размер кадра зависит от их размера. Каждому фрейму также нужны (я думаю) два дополнительных слова для хранения сохраненного указателя фрейма и сохраненного адреса возврата.
Обратите внимание, что в рекурсивном алгоритме вы можете иметь более одного кадра стека для одного «уровня рекурсии». Для writeObject
(в Java 8) используемый алгоритм является рекурсивным, и обычно имеется 4 кадра на уровень сериализуемой структуры данных:
writeObject0
writeOrdinaryObject
writeSerialData
defaultWriteFields
writeObject0
etcetera
Фактические размеры кадров будут зависеть от платформы из-за различий в компиляторах и изменений в реализации ObjectInputStream / ObjectOutputStream. Лучше попытаться (приблизительно) измерить необходимое пространство стека, чем пытаться предсказать размеры кадра из первых принципов.
Еще один вопрос: будет ли каждый поток иметь размер стека 3000k, если я поставлю параметр JVM -Xss3000k?
Да ... за исключением того, что я описал выше.
Одно из возможных решений вашей дилеммы - создать специальный поток с огромным стеком, который вы используете для сериализации. Аналогичный поток с огромным стеком потребуется для десериализации. Для остальных потоков размер стека по умолчанию должен подойти.
Другие возможные решения:
Реализуйте методы
writeReplace
иreadResolve
, чтобы сгладить родительскую структуру ваших объектов epc в массив, чтобы не получить глубокую рекурсию. (Очевидно, сглаживание / сглаживание должно выполняться нерекурсивно.)Сделайте то же сведение перед вызовом
writeObject
и т.д.Используйте другой механизм сериализации или, возможно, собственный.
Будет ли каждый поток иметь размер стека 3000k, если я поставлю параметр JVM -Xss3000k?
Есть конструктор, определяющий размер стека для нового потока. Все потоки, которые не используют этот специальный конструктор, получат размер стека по умолчанию, указанный в параметре JVM (и это будет охватывать все потоки, если вы не создадите их самостоятельно).
Если вашему приложению не требуется большое количество потоков, повышенный предел, вероятно, не является проблемой и является самым простым решением.
Если нет, вы можете создать такой поток с большим стеком, особенно для выполнения вашего глубоко рекурсивного кода сериализации. Вы можете обернуть его в Executor и вызвать в него код приложения.
что указывает размер стека 1 МБ в JVM, поскольку я понятия не имею, какой размер кадра стека?
Это действительно немного подвижная цель. Вы должны сделать это настраиваемым, и эксперименты подскажут вам, что это за настройка.
Даже Javadoc говорит
Из-за платформенно-зависимого характера поведения этого конструктора при его использовании следует проявлять особую осторожность. Размер стека потока, необходимый для выполнения данного вычисления, вероятно, будет варьироваться от одной реализации JRE к другой. В свете этого изменения может потребоваться тщательная настройка параметра размера стека, и настройка может потребоваться повторить для каждой реализации JRE, в которой должно выполняться приложение.
Похожие вопросы
Связанные вопросы
Новые вопросы
java
Java — это высокоуровневый объектно-ориентированный язык программирования. Используйте этот тег, если у вас возникли проблемы с использованием или пониманием самого языка. Этот тег часто используется вместе с другими тегами для библиотек и/или фреймворков, используемых разработчиками Java.