Я читал и тестировал и стучал головой о стену в течение дня из-за этой ошибки.Java `OutOfMemoryError` при создании <100 нитей
У меня есть Java-код в класс под названием Listener
, который выглядит, как этот
ExecutorService executor = Executors.newFixedThreadPool(NTHREADS);
boolean listening = true;
int count = 0;
while (listening) {
Runnable worker;
try {
worker = new ServerThread(serverSocket.accept()); // this is line 254
executor.execute(worker);
count++;
logger.info("{} threads started", count);
} catch (Exception e1){
//...
}
}
Я донастроить JVM параметры которой -Xmx
(где-то от 1 до 15G) и -Xss
(где-то от 104K до 512M). Сервер имеет 24 ГБ ОЗУ, но также должен работать с базой данных, поддерживающей программу.
После создания 2-20 нитей (несколько десятков существуют в другом месте в программе, а), я получаю ошибку
Exception in thread "Thread-0" java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start0(Native Method)
at java.lang.Thread.start(Thread.java:657)
at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:943)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1325)
at xxx.Listener.run(Listener.java:254)
$java -version
выходы:
java version "1.6.0_24"
OpenJDK Runtime Environment (IcedTea6 1.11.1) (fedora-65.1.11.1.fc16-x86_64)
OpenJDK 64-Bit Server VM (build 20.0-b12, mixed mode)
Там всегда большая количество свободной памяти в системе, когда это происходит, и другие программы продолжают выполнять штраф. Что заставляет Java думать, что у нее больше нет памяти для новых потоков?
UPDATE: Возможно, это больше, чем я думала, мне удалось получить эту ошибку (только один раз), когда я использовал ^C
:
OpenJDK 64-Bit Server VM warning: Exception java.lang.OutOfMemoryError occurred dispatching signal SIGINT to handler- the VM may need to be forcibly terminated
и то же самое произошло, когда я пытался убить клиент (также написанный на Java и работающий на одном сервере, это единственный поток, который читает файл и отправляет его на сервер через сокет), поэтому существует определенная предел за пределами JVM, заставляющий вмешиваться в другой, но я не могу себе представить, что, если у меня все еще есть свободная память и я вообще не использую swap? Сервер -Xmx1G -Xss104k Клиент -Xmx10M
UPDATE2: Бросив PERL Forks::Super
библиотеку и запуск клиентов из Баша позволь мне получить до 34 потоков, прежде чем сервер упал с OOME, поэтому запуск нескольких клиентов, безусловно, оказали влияние на сервере, но в то же время я все равно могу запустить более 34 (68, если подсчитывать клиентов) java-потоков за раз. Какие системные ресурсы блокируют создание большего количества потоков (т. Е. Где я должен искать свиней)? Когда все (клиенты, сервер, GC ...) бежит из памяти в то же время, top
говорит это о моем CPU и памяти:
Cpu(s): 0.0%us, 0.0%sy, 0.0%ni,100.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 24681040k total, 1029420k used, 23651620k free, 30648k buffers
Swap: 26836988k total, 0k used, 26836988k free, 453620k cached
Update3: ли в журнал hs_error ниже, показывают, что мой java не 64 бит?
# There is insufficient memory for the Java Runtime Environment to continue.
# Cannot create GC thread. Out of system resources.
# Possible reasons:
# The system is out of physical RAM or swap space
# In 32 bit mode, the process size limit was hit
# Possible solutions:
# Reduce memory load on the system
# Increase physical memory or swap space
# Check if swap backing store is full
# Use 64 bit Java on a 64 bit OS
# Decrease Java heap size (-Xmx/-Xms)
# Decrease number of Java threads
# Decrease Java thread stack sizes (-Xss)
# Set larger code cache with -XX:ReservedCodeCacheSize=
# This output file may be truncated or incomplete.
#
# JRE version: 6.0_24-b24
# Java VM: OpenJDK 64-Bit Server VM (20.0-b12 mixed mode linux-amd64 compressed oops)
# Derivative: IcedTea6 1.11.1
# Distribution: Fedora release 16 (Verne), package fedora-65.1.11.1.fc16-x86_64
Является ли ServerThread экземпляром java.lang.Thread? то он должен быть запущен с Thread.start(), и пул потоков бесполезен. Если нет, то как вы собираетесь обслуживать соединение сокета с простым Runnable? Это сложно, так как задачи под управлением threadpool не могут дождаться ввода, или может возникнуть головоломка потока (вид взаимоблокировки). –
ServerThread - это плохо названный класс моего собственного создания. Public class ServerThread реализует Runnable {... public void run() {...} ...} ' Я вижу вашу обеспокоенность в связи с тем, что может быть плохо ждать вход в пул (есть функция тайм-аута), но я не хочу создавать новый поток каждый раз, когда клиент подключается, - это было бы огромными накладными расходами для относительно коротких взаимодействий и все равно не решило бы проблемы с созданием потоков. – kaz
Вы проверили, сколько потоков вы можете создать в более простом приложении? – Jivings