Подтвердить что ты не робот

Ошибка памяти Java: невозможно создать новый собственный поток

Я получаю эту ошибку на моем сервере UNIX при запуске моего java-сервера:

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:640)
at [... where ever I launch a new Thread ...]

Это происходит каждый раз, когда у меня около 600 потоков.

Я установил эту переменную на сервере:

$> ulimit -s 128

Что мне кажется странным, так это результат этой команды, которую я запускал, когда ошибка произошла в последний раз:

$> free -m
              total       used       free     shared    buffers     cached
Mem:          2048        338       1709          0          0          0
-/+ buffers/cache:        338       1709
Swap:            0          0          0

Я запускаю свой Java-сервер следующим образом:

$> /usr/bin/java -server -Xss128k -Xmx500m -jar /path/to/myJar.jar

Моя версия debian:

$> cat /etc/debian_version
5.0.8

Моя версия java:

$> java -version
java version "1.6.0_26"
Java(TM) SE Runtime Environment (build 1.6.0_26-b03)
Java HotSpot(TM) 64-Bit Server VM (build 20.1-b02, mixed mode)

Мой вопрос: я прочитал в Интернете, что моя программа должна обрабатывать что-то вроде 5000 потоков или около того. Итак, что происходит, и как исправить пожалуйста?


Изменить: это вывод ulimit -a при открытии оболочки:

core file size          (blocks, -c) unlimited
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 794624
max locked memory       (kbytes, -l) 32
max memory size         (kbytes, -m) unlimited
open files                      (-n) 100000
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 794624
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

Я запускаю script как демон из init.d, и это то, что я запускаю:

DAEMON=/usr/bin/java
DAEMON_ARGS="-server -Xss128k -Xmx1024m -jar /path/to/myJar.jar"
ulimit -s 128 && ulimit -n 10240 && start-stop-daemon -b --start --quiet --chuid $USER -m -p $PIDFILE --exec $DAEMON -- $DAEMON_ARGS \
    || return 2

Edit2: Я столкнулся с этим вопросом с помощью теста java для потоков: how-many-threads-can-a-java-vm-support

    public class DieLikeADog { 
        private static Object s = new Object(); 
        private static int count = 0; 
        public static void main(String[] argv){ 
            for(;;){ 
                new Thread(new Runnable(){ 
                        public void run(){ 
                            synchronized(s){ 
                                count += 1; 
                                System.err.println("New thread #"+count); 
                            } 
                            for(;;){ 
                                try { 
                                    Thread.sleep(100); 
                                } catch (Exception e){ 
                                    System.err.println(e); 
                                } 
                            } 
                        } 
                    }).start(); 
            } 
        } 
    } 

На моем сервере программа вылетает после 613 потоков. Теперь я уверен, что это ненормально и связано только с моей конфигурацией сервера. Может ли кто-нибудь помочь?


Изменить 3: Я столкнулся с этой статьей и многими другими, объяснив, что linux не может создавать 1000 потоков, но вы, ребята, говорите мне, что можете сделайте это в своих системах. Я не понимаю.

Я также запускал этот script на моем сервере: threads_limits.c, а предел составляет около 620 потоков.

Мой сайт теперь отключен, и это самое худшее, что могло случиться с моим проектом. Я не знаю, как перекомпилировать glibc и этот материал. Это слишком много работы imo.

Я думаю, я должен переключиться на сервер Windows. Поскольку ни одна из настроек, предложенных на этой странице, не вносила никаких изменений: ограничение на мою систему составляет от 600 до 620 потоков, независимо от того, какая программа была задействована.

4b9b3361

Ответ 1

Только что получил следующую информацию: Это ограничение, наложенное моим хост-провайдером. Это не имеет ничего общего с программированием или linux.

Ответ 2

Основная операционная система (в этом случае Debian Linux) не позволяет процессу создавать больше потоков. См. Здесь, как повысить максимальную сумму: Максимальное количество потоков для процесса в Linux?

Я читал в Интернете, что моя программа должна обрабатывать что-то вроде 5000 или около того.

Это зависит от ограничений, установленных для ОС, количества запущенных процессов и т.д. С помощью правильных настроек вы можете легко достичь этого количества потоков. Я запускаю Ubuntu на своем собственном компьютере, и я могу создать около 32000 потоков, прежде чем нажимать лимит на одной программе Java со всеми моими "нормальными вещами", работающими на фоне (это было сделано с помощью тестовой программы, которая только что создала потоки, которые спал немедленно в бесконечном цикле). Естественно, что большое количество потоков, фактически занимающихся чем-то, вероятно, быстро закричало бы потребительское оборудование.

Ответ 3

Можете ли вы попробовать ту же команду с меньшим размером стека "-Xss64k" и передать результаты?

Ответ 4

Я начинаю подозревать, что "Native Posix Thread Library" отсутствует.

>getconf GNU_LIBPTHREAD_VERSION

Должно вывести что-то вроде:

NPTL 2.13

Если нет, установка Debian будет испорчена. Я не уверен, как это исправить, но установка Ubuntu Server кажется хорошим шагом...

для ulimit -n 100000; (open fd: s) следующая программа должна иметь возможность обрабатывать 32 000 потоков или около того.

Попробуйте:

package test;

import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.concurrent.Semaphore;

public class Test {

    final static Semaphore ss = new Semaphore(0);


    static class TT implements Runnable {

        @Override
        public void run() {
            try {
                Socket t = new Socket("localhost", 47111);
                InputStream is = t.getInputStream();
                for (;;) {
                    is.read();
                }

            } catch (Throwable t) {
                System.err.println(Thread.currentThread().getName() + " : abort");
                t.printStackTrace();
                System.exit(2);
            }

        }
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        try {

            Thread t = new Thread() {
                public void run() {
                    try {
                        ArrayList<Socket> sockets = new ArrayList<Socket>(50000);
                        ServerSocket s = new ServerSocket(47111,1500);
                        ss.release();

                        for (;;) {
                            Socket t = s.accept();
                            sockets.add(t);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        System.exit(1);

                    }
                }
            };


            t.start();
            ss.acquire();


            for (int i = 0; i < 30000; i++) {

                Thread tt = new Thread(new TT(), "T" + i);
                tt.setDaemon(true);
                tt.start();
                System.out.println(tt.getName());
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    return;
                }
            }

            for (;;) {
                System.out.println();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    return;
                }
            }

        } catch (Throwable t) {
            t.printStackTrace();
        }
    }
}

Ответ 5

В вашей JVM не удается выделить стек или некоторую другую память в потоке. Уменьшение размера стека с помощью -Xss поможет увеличить количество потоков, которые вы можете создать до возникновения OOM (но JVM не позволит вам установить произвольно малый размер стека).

Вы можете подтвердить, что это проблема, видя, как количество созданных потоков изменяется при настройке -Xss или путем запуска strace на вашей JVM (вы почти наверняка увидите mmap() возвращающий ENOMEM до того, как будет создано исключение).

Проверьте также свой ulimit на виртуальный размер, т.е. ulimit -v. Увеличение этого ограничения должно позволить вам создавать больше потоков с одинаковым размером стека. Обратите внимание, что ограничение размера резидентного набора (ulimit -m) неэффективно в текущем ядре Linux.

Кроме того, уменьшение -Xmx может помочь, оставив больше памяти для стеков потоков.

Ответ 6

Его выход из памяти.

Также нужно изменить ulimit. Если ваша ОС не дает вашему приложению достаточно памяти -Xmx, я полагаю, это не имеет никакого значения.

Я думаю, что -Xmx500m не имеет никакого эффекта.

Попробуйте

ulimit -m 512m  с -Xmx512m