حد منخفض لسلسلة عمليات Java الفردية في Red Hat Linux
سؤال
أواجه مشكلة على جهاز اختبار يعمل بنظام Red Hat Linux (إصدار kernel هو 2.4.21-37.ELsmp) باستخدام Java 1.6 (1.6.0_02 أو 1.6.0_04).تكمن المشكلة في أنه بمجرد إنشاء عدد معين من سلاسل العمليات في مجموعة سلاسل رسائل واحدة، يصبح نظام التشغيل غير راغب أو غير قادر على إنشاء المزيد.
يبدو أن هذا خاص بإنشاء سلاسل رسائل Java، حيث كان برنامج C Thread-limit قادرًا على إنشاء حوالي 1.5 ألف سلسلة رسائل.بالإضافة إلى ذلك، هذا لا يحدث مع Java 1.4 JVM...يمكنه إنشاء أكثر من 1.4 كيلو بايت من المواضيع، على الرغم من أنه من الواضح أنه يتم التعامل معها بشكل مختلف فيما يتعلق بنظام التشغيل.
في هذه الحالة، يكون عدد الخيوط التي يتم قطعها عندها 29 خيطًا فقط.يمكن اختبار ذلك باستخدام برنامج Java بسيط يقوم فقط بإنشاء سلاسل رسائل حتى يحصل على خطأ ثم يطبع عدد سلاسل الرسائل التي أنشأها.الخطأ هو أ
java.lang.OutOfMemoryError: unable to create new native thread
يبدو أن هذا لا يتأثر بأشياء مثل عدد مؤشرات الترابط المستخدمة من قبل العمليات أو المستخدمين الآخرين أو إجمالي مقدار الذاكرة التي يستخدمها النظام في ذلك الوقت.لا يبدو أن إعدادات JVM مثل Xms وXmx وXss تغير أي شيء أيضًا (وهو أمر متوقع، مع الأخذ في الاعتبار أن المشكلة تتعلق بإنشاء سلسلة عمليات نظام التشغيل الأصلي).
إخراج "ulimit -a" هو كما يلي:
core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited file size (blocks, -f) unlimited max locked memory (kbytes, -l) 4 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 stack size (kbytes, -s) 10240 cpu time (seconds, -t) unlimited max user processes (-u) 7168 virtual memory (kbytes, -v) unlimited
لا يبدو أن حد عملية المستخدم هو المشكلة.البحث عن معلومات حول ما يمكن أن يكون خطأ لم يظهر كثيرًا، ولكن هذا المشنور يبدو أنه يشير إلى أن بعض نواة Red Hat على الأقل تقصر العملية على 300 ميجابايت من الذاكرة المخصصة للمكدس، وعند 10 ميجابايت لكل مؤشر ترابط للمكدس، يبدو أن المشكلة قد تكون موجودة (على الرغم من أنها تبدو غريبة وغير محتملة أيضًا).
لقد حاولت تغيير حجم المكدس باستخدام "ulimit -s" لاختبار ذلك، ولكن أي قيمة بخلاف 10240 وJVM لا يبدأ بخطأ:
Error occurred during initialization of VM Cannot create VM thread. Out of system resources.
يمكنني عمومًا التجول في Linux، لكنني لا أعرف الكثير عن تكوين النظام، ولم أتمكن من العثور على أي شيء يعالج هذا النوع من المواقف على وجه التحديد.سيكون موضع تقدير أي أفكار حول النظام أو إعدادات JVM التي قد تسبب ذلك.
التعديلات:تشغيل برنامج الحد من الخيط الذي ذكره طيدة, ، لم يكن هناك أي فشل حتى حاول إنشاء مؤشر الترابط رقم 1529.
لم تحدث المشكلة أيضًا باستخدام 1.4 JVM (تحدث مع 1.6.0_02 و1.6.0_04 JVMs، ولا يمكن اختبارها باستخدام 1.5 JVM في الوقت الحالي).
رمز اختبار الخيط الذي أستخدمه هو كما يلي:
public class ThreadTest {
public static void main(String[] pArgs) throws Exception {
try {
// keep spawning new threads forever
while (true) {
new TestThread().start();
}
}
// when out of memory error is reached, print out the number of
// successful threads spawned and exit
catch ( OutOfMemoryError e ) {
System.out.println(TestThread.CREATE_COUNT);
System.exit(-1);
}
}
static class TestThread extends Thread {
private static int CREATE_COUNT = 0;
public TestThread() {
CREATE_COUNT++;
}
// make the thread wait for eternity after being spawned
public void run() {
try {
sleep(Integer.MAX_VALUE);
}
// even if there is an interruption, dont do anything
catch (InterruptedException e) {
}
}
}
}
إذا قمت بتشغيل هذا باستخدام 1.4 JVM، فسيتم تعليقه عندما لا يتمكن من إنشاء المزيد من سلاسل الرسائل ويتطلب القتل -9 (على الأقل حدث ذلك بالنسبة لي).
المزيد من التحرير:
اتضح أن النظام الذي يواجه المشكلة يستخدم نموذج ترابط LinuxThreads بينما يستخدم نظام آخر يعمل بشكل جيد نموذج NPTL.
المحلول 2
أدى تحديث النواة إلى إصدار أحدث (2.6.something) باستخدام خيوط NPTL إلى إصلاح هذه المشكلة.
نصائح أخرى
هل نظرت إلى هذا المورد؟تنص على أنه يجب أن تكون قادرًا على تشغيل Thread-Limit للعثور على الحد الأقصى لعدد سلاسل الرسائل ويمكنك تعديله عن طريق تجميع glibc.
هذا مع Ubuntu Linux (ذاكرة الوصول العشوائي سعة 1 جيجابايت)
dsm@localhost:~$ javac ThreadTest.java
dsm@localhost:~$ java ThreadTest
8113
dsm@localhost:~$ java -version
java version "1.6.0_07"
Java(TM) SE Runtime Environment (build 1.6.0_07-b06)
Java HotSpot(TM) Client VM (build 10.0-b23, mixed mode, sharing)
dsm@localhost:~$
هل يمكنك تجربتها مع JRockit JVM؟IIRC، كان لديه نموذج ترابط مختلف عن المخزون Sun JVM.
الإعدادات في /etc/security/limits.d/90-nproc.conf
قد تغلب الخاص بك /etc/security/limits.conf
إعدادات.قد يتسبب ذلك في تصرف النظام بطريقة مختلفة كما هو موضح في ulimit -u
.