2016-06-08 24 views
2

Ich versuche, eine Java-Anwendung auszuführen, genauer gesagt ein Glas ein zusammengestellt, mit execve() in c
etwas wie folgt aus:verhindern Java-Programm von der Öffnung Threads

char *cmd[] = {"a.jar"}; 
execve("a.jar",cmd,NULL); 

, die funktioniert OK, aber wenn ich versuche, die Anzahl der Threads zu begrenzen, die dieses Programm öffnen können so etwas mit:

struct rlimit rlp; 
rlp.rlim_cur = rlp.rlim_max = limit_nproc; 
setrlimit(RLIMIT_NPROC,&rlp); 

ich habe ein Problem mit der JVM, die Threads öffnen würde, und ich bin zu verhindern, dass so habe ich diesen Fehler:

Wie kann ich verhindern, dass die in der Java-Anwendung geöffneten Threads geöffnet werden, aber nicht die von der JVM geöffneten Threads? !

Bitte beachten Sie, ist die Frage, wie Benutzer-Threads zu verhindern, aber nicht System-Threads, ich brauche eine Beschränkung auf die Fahrumgebung wie das, was ich in meinem zweiten Code „RLIMIT_NPROC“ tat

und Dank!

+0

Erkennung seines Happenings würde die Arbeit mit mir auch –

+0

Mögliche Duplikate von [Java führen aus Speicherproblem] (http://stackoverflow.com/questions/18078859/java-run-out-of-memory-issue) –

+0

Wenn Sie die Anzahl der Prozesse/Threads begrenzen, wird Java nicht daran gehindert, Threads zu starten. Wenn Sie nicht mehr genügend Arbeitsspeicher oder Systemressourcen haben, um Threads zu erstellen, wird die Einstellung von 'RLIMIT_NPROC' auf eine niedrigere Zahl nur dazu führen, dass Ihr Java-Prozess die Threads * schneller * auslässt. –

Antwort

2

Dies kann mit JVMTI Agent erreicht werden.

Die Idee ist es, native Thread.start0() Methode abzufangen und eine Ausnahme zu werfen, wann immer es aufgerufen wird.

Hier ist ein Beispielagenten in C++ geschrieben:

#include <jvmti.h> 

// Original native implementation of Thread.start0(), if you wish to call it 
extern "C" void JNICALL JVM_StartThread(JNIEnv* env, jthread thread); 

void JNICALL StartThreadHook(JNIEnv* env, jthread thread) { 
    env->ThrowNew(env->FindClass("java/lang/Error"), "Threads forbidden"); 
} 

void JNICALL VMInit(jvmtiEnv* jvmti, JNIEnv* env, jthread thread) { 
    // After VM is initialized, intercept Thread.start0() with our hook function 
    jclass thread_class = env->FindClass("java/lang/Thread"); 
    JNINativeMethod start0 = {(char*)"start0", (char*)"()V", (void*)StartThreadHook}; 
    env->RegisterNatives(thread_class, &start0, 1); 
} 

JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM* vm, char* options, void* reserved) { 
    jvmtiEnv* jvmti; 
    vm->GetEnv((void**)&jvmti, JVMTI_VERSION_1_0); 

    jvmtiEventCallbacks callbacks = {0}; 
    callbacks.VMInit = VMInit; 
    jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks)); 
    jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, NULL); 

    return 0; 
} 

den Agenten Kompilieren:

g++ -fPIC -shared -olibnothreads.so -Wl,-soname,libnothreads.so nothreads.cpp 

Führen Sie die Anwendung mit dem Agenten:

java -agentpath:/path/to/libnothreads.so -jar app.jar 

Beachten Sie, dass Sie können auch Verwenden Sie JVMTI, um eine benutzerdefinierte Logik zu implementieren, um zu ermöglichen, wann neue Threads zugelassen oder abgelehnt werden. Zum Beispiel werden ThreadStart und ThreadEnd Ereignisse helfen, erstellte Threads zu zählen. GetStackTrace Funktion hilft zu finden, welche Klassen versuchen, einen Thread zu erstellen.

+0

Ich frage mich, ob Sie das gleiche durch Meta-Programmierung in groovy erreichen können. Wäre trotzdem eine interessante Übung. .. – Chewy

+0

Ich kann den Link, den Sie dem JVMTI-Agenten zur Verfügung gestellt haben, nicht sehen. Ich kann in einem Land sein, in dem diese Seite verboten ist. Daher werde ich das von Ihnen bereitgestellte Beispiel verwenden, wenn Sie mir andere nützliche Beispiele geben können Ich würde Lichtung sein, danke viel das war wirklich hilfreich :) –

+0

@AliKanaan Der Link führt im Grunde zu JVM Tool Interface-Spezifikation, können Sie es an anderer Stelle finden. Weitere JVMTI-Beispiele finden sich in offiziellen JDK-Demos im Verzeichnis 'jvmti'. Wie auch immer, das obige Beispiel wird genau das tun, wonach Sie gefragt haben. – apangin

0

how can I prevent the threads opened in the java application but not those opened by the JVM ?

Ich bin nicht sicher, Sie können. Das Verhindern, dass die JVM Threads erstellt, ist so, als würde man die Anzahl der von ihr erstellten String s begrenzen. Wenn der Code einen Thread erstellt, können Sie nichts dagegen tun.

Über die einzige Sache, die helfen könnte, ist die Sicherheitsrichtlinie, aber wie ich es gelesen habe, Thread-Erstellung wird nicht gesteuert. Siehe Java's docs on the permissions under control.

java.lang.OutOfMemoryError: Cannot create GC thread. Out of system resources.

Wie Sie wahrscheinlich wissen, zusätzlich zu dem „main“ Thread startet Java eine Reihe von anderen JVM spezifischen Themen, die im Hintergrund arbeiten. Zum Beispiel startet ein einfaches main(String[] args) Programm "main" und weitere 5 Threads für mich, die die GC-Threads nicht enthalten, glaube ich. Die JVM-Threads werden für die Speicherverwaltung und andere wichtige Aufgaben benötigt. Wenn Sie Threads bis zu einem Punkt begrenzen, an dem die GC-Threads nicht starten können, wird die JVM überhaupt nicht ausgeführt werden können.

<HACK> Eine Sache, die Sie tun können, ist die Anzahl der Threads auf die genaue Anzahl zu begrenzen, um die System-Threads und "main" aufzunehmen. Innerhalb von main(), bevor der Benutzercode eine Möglichkeit hat, weitere Threads zu starten, können Sie die Anzahl der ausgeführten Threads unter Verwendung von Thread.getAllStackTraces().size() zählen und dann Ihre Betriebssystemgrenzwerte auf diese Zahl setzen. Wenn dies immer noch fehlschlägt, dann versuchen Sie 1 oder 2 zu size() hinzuzufügen, um andere Hintergrundthreads zu berücksichtigen, die in der Stack-Ablaufverfolgung nicht berücksichtigt wurden. </HACK>

All dies gesagt, die Frage, die ich habe, ist, was versuchst du zu erreichen? Wenn Sie sich Sorgen machen, dass ein Java-Prozess Ihren Server übernimmt, frage ich mich, ob es Betriebssystemeinstellungen gibt, die besser steuern, wie viele Systemressourcen dem Prozess zur Verfügung gestellt werden. Wie wäre es, die Nebenläufigkeit statt der Anzahl der Threads zu begrenzen? Vielleicht nach Thread-Affinitätseinstellungen suchen? Dies wäre jedoch sehr Betriebssystem abhängig.

+0

Dank grau für Ihre Antwort dachte ich über das, was Sie als Hack vorgeschlagen, aber ein Problem zu stellen, darüber nachzudenken, was ist, wenn die Anzahl der Prozesse für die JVM und die Hauptklasse von 2 Threads oder sogar eine zwischen unterscheiden können zwei verschiedene Läufe für zwei verschiedene Codes? ; Was ist jedoch, wenn diese genaue Anzahl von Threads zwischen den verschiedenen Versionen unterschiedlich ist? : \ ?? !! ist garantiert, dass sich die Anzahl der Threads nicht ändert! –

+0

Leider ist @AliKanaan nicht zwischen verschiedenen Java-Versionen garantiert, sondern unterschiedliche Läufe mit der gleichen JVM-Version bis zum Haupt _should_ fork die gleiche Anzahl von System-Threads. Ich glaube nicht, dass es dort Schwankungen gibt, aber ich bin mir nicht 100% sicher. Daher der Hack. Viel Glück. – Gray