Linux/C++/Pthreads auf JVM zugreifen, thread safe?

gruena

Mitglied
Hallo Community,

ich habe ein C++-Programm und würde sehr gerne die JVM benutzen, um Zugriff auf all die Java-Klassen zu bekommen (z.B. MySQL). Das Programm hat mehrere Threads, wobei jeder Queries über eine einzige Connection senden können soll.

Jetzt habe ich schon eine Testanwendung mit JNI programmiert, in der ich auch über FindClass/GetMethodID/NewObject Funktionen aus der JVM aufrufen kann.

Kann man nun einfach in main() die JVM in eine globale Variable erstellen, sich mit MySQL verbinden, dann 10 Threads spawnen und jeder Thread darf dann die JVM benutzen (welche dann Queries an den MySQL-Server sendet)?

Liebe Grüße,
gruena
 

KrokoDiehl

Top Contributor
Doch schon, aber soweit noch nicht... kannst du es nicht "einfach" ausprobieren? Ich weiß vor allem dass du bei "längeren nativen Anwendungen" immer die
Code:
JNIEnv*
und
Code:
jobject
Objekte vom letzten JNI-Aufruf nehmen musst, weil die alten Referenz verfallen.
 

gruena

Mitglied
Hey KrokoDiehl, danke für deine Antwort.

Das ist, was ich bislang habe:

java.c (man verzeihe mir eventuelle Dummheit beim Setzen der java.class.path/java.library.path, ich bin noch nicht lange mit Java am Programmieren)
Code:
#include <stdlib.h>
#include <string.h>

#include <jni.h>

#include <pthread.h>

JavaVM *jvm;

void jvm_init()
{
	JNIEnv *env;
	JavaVMInitArgs vm_args;
	JavaVMOption options[3];
	int nbOptions;
	jint res;
	char classPath[128], libraryPath[128];

	strcpy(classPath, "-Djava.class.path=/usr/share/java:/root/java32/mysql-connector-java.jar:/root/java32");   /* Path of the SwingManu.class file */
	strcpy(libraryPath, "-Djava.library.path=/root/java32:/usr/lib/jvm/java-6-openjdk/jre/lib/amd64");     /* Path of the libNativeMethods.so library */
	nbOptions=0;
	options[0].optionString = classPath;   nbOptions++;
	options[1].optionString = libraryPath; nbOptions++;
	vm_args.version  = JNI_VERSION_1_2;                   /* Specifies the JNI version used */
	vm_args.options  = options;
	vm_args.nOptions = nbOptions;
	vm_args.ignoreUnrecognized = JNI_TRUE;                 /* JNI won't	complain about unrecognized options */
	res = JNI_CreateJavaVM(&jvm,(void **)&env,&vm_args);
	
	#if 0
	int ret;
	ret = (*jvm)->AttachCurrentThread(jvm, (void**)&env, NULL);
	if (ret != JNI_OK)
		printf("[ERROR] MAIN AttachCurrentThread() != JNI_OK\n");
	#endif
}

void *thread_worker(void *data)
{
	int ret;
	
	JNIEnv *env;
	ret = (*jvm)->AttachCurrentThread(jvm, (void**)&env, NULL);
	if (ret != JNI_OK)
		printf("[ERROR] AttachCurrentThread() != JNI_OK\n");
	
	#if 0
	jobject lock; // THIS ISNT WORKING, WHERE SHALL I GET AN OBJECT AS LOCK?
	ret = (*env)->MonitorEnter(env, lock);
	if (ret != JNI_OK)
		printf("[ERROR] MonitorEnter() != JNI_OK\n");
	#endif

	jclass helloWorldClass;
	jmethodID mainMethod;
	jobjectArray applicationArgs;
	jstring applicationArg0;

	helloWorldClass = (*env)->FindClass(env, "Quadrat");
	mainMethod = (*env)->GetStaticMethodID(env, helloWorldClass, "main", "([Ljava/lang/String;)V");
	applicationArgs = (*env)->NewObjectArray(env, 1, (*env)->FindClass(env, "java/lang/String"), NULL);
	applicationArg0 = (*env)->NewStringUTF(env, "From-C-program"); // TOOOOOOOOOODOOOOOOOO: free?
	(*env)->SetObjectArrayElement(env, applicationArgs, 0, applicationArg0);
	(*env)->CallStaticVoidMethod(env, helloWorldClass, mainMethod, applicationArgs);

	#if 0
	ret = (*env)->MonitorExit(env, lock);
	if (ret != JNI_OK)
		printf("[ERROR] MonitorExit() != JNI_OK\n");
	#endif
	
	ret = (*jvm)->DetachCurrentThread(jvm);
	if (ret != JNI_OK)
		printf("[ERROR] DetachCurrentThread() != JNI_OK\n");
}

int main (int argc, char *argv[])
{

	jvm_init();
	
	// just for testing
	thread_worker(NULL);
	thread_worker(NULL);
	thread_worker(NULL);

	int i;
	for (i=0; i<200; i++)
	{
		pthread_t thread;
		pthread_create(&thread, NULL, thread_worker, NULL);
		usleep(1000 * 20); // immediatly = many jvm errors
	}
	
	usleep(1000*1000 * 10); // wait 10 seconds for end of all threads
	printf("\n");
}

Kompilieren: [c]gcc java.c -I/usr/lib/jvm/java-6-openjdk/include/ -ljvm -L/usr/lib/jvm/java-6-openjdk/jre/lib/amd64/server/[/c]

Quadrat.java (mysql() fragt vom Server eine Zahl zwischen 0-9 ab und schreibt sie + " "):
Java:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Quadrat
{
	static void mysql()
	{
		Connection con = null;
		Statement st = null;
		ResultSet rs = null;
		String host = "127.0.0.1";
		String user = "...";
		String pass = "...";
		String db = "...";
		int port = 3306;
		
		try {
			Class.forName("com.mysql.jdbc.Driver").newInstance();
		} catch (Exception e) {
			System.err.println ("Cannot load database driver: " + e.toString());
		}
		
		try {
			String url = "jdbc:mysql://" + host + ":" + port + "/" + db;
			con = DriverManager.getConnection(url, user, pass);
			st = con.createStatement();
			rs = st.executeQuery("SELECT FLOOR(RAND()*1000%10)");
			if (rs.next())
				System.out.print(rs.getString(1) + " ");
		} catch (SQLException ex) {
			Logger lgr = Logger.getLogger(Quadrat.class.getName());
			lgr.log(Level.SEVERE, ex.getMessage(), ex);
		} finally {
			try {
				if (rs != null)
					rs.close();
				if (st != null)
					st.close();
				if (con != null)
					con.close();

			} catch (SQLException ex) {
				Logger lgr = Logger.getLogger(Quadrat.class.getName());
				lgr.log(Level.WARNING, ex.getMessage(), ex);
			}
		}
	}
	
	public static void main(String[] args)
	{
		mysql();
	}
}
Kompilieren: [c]javac Quadrat.java[/c]

Ok, beides muss in /root/java32 und dann kann man das Duo ausführen mit: [c]LD_LIBRARY_PATH=/usr/lib/jvm/java-6-openjdk/jre/lib/amd64/server/ ./a.out[/c]

Jeder Thread attached sich selbst, und bezieht aus AttachCurrentThread seinen [c]JNIEnv*[/c]-Pointer.

Leider gibt es Probleme:
1) die Funktion thread_worker() ruft die Java-Funktion mysql() IMMER nur 115x auf
2) wenn ich die Threads zu schnell hintereinander starte, dann meldet die JVM "stack guard pages"-Fehler

Also irgendwas scheint noch grundlegend falsch zu sein, aber wenn ich nur wüsste, was es denn ist. Ich finde auch keine gute Dokumentation seitens Oracle dazu. Wenn man sich bei Oracle durch die Support->Product Documentation klickt, bekommt man sogar 404er. Die habens wohl nicht nötig.

MonitorEnter/MonitorExit weiß ich nicht zu benutzen, da [c]jobject lock[/c] ja ein Objekt braucht, aber wo soll ich das in einem frischen Thread herzaubern? Ich denke, damit könnte man schonmal Punkt 2 lösen.

Ich danke für jeden noch-so-kleinen Hinweis. :)
 

tfa

Top Contributor
Was ist denn das Ziel? Warum möchtest du von einem C++ Programm auf Java zugreifen? Nur wegen DB-Zugriff? Dann würde ich sagen, programmier das doch auch in C++. JNI ist eher dafür gedacht, von Java-Programmen auf system- oder hardware-nahe Funktionen zuzugreifen.
 

gruena

Mitglied
Einerseits soll das C++-Programm in Java programmiert werden können. Anderseits kann ich nicht auf Anhieb das komplette C++-Ökosystem in Java abbilden, sodass ich dann an noch kritischen Stellen die JVM über C++ benutzen möchte. :)
 

irgendjemand

Top Contributor
Einerseits soll das C++-Programm in Java programmiert werden können. Anderseits kann ich nicht auf Anhieb das komplette C++-Ökosystem in Java abbilden, sodass ich dann an noch kritischen Stellen die JVM über C++ benutzen möchte. :)

davon war auch nicht die rede .. sondern genau umgekehrt : das du den DB-teil den du jetzt in java implementiert hast dierekt in C++ schreibst ...

JNI ist nun mal halt eher dafür gedacht java die möglichkeit zu geben native libs zu nutzen ...
natürlich geht es auch anders rum *wie man ja hier sieht* ... aber das ist eigentlich nur für callbacks gedacht und nicht zur dierekten verwendung
 

gruena

Mitglied
Was soll denn daran ungewöhnlich sein? Wenn man die JVM in C++ einbindet, dann muss es unbedingt so sein, dass man .java-Code aufrufen kann, und nicht nur als Callback (wie soll man es denn sonst mit Java scripten). Genau dafür gibt es ja JNI_CreateJavaVM/AttachCurrentThread und co.
 

KrokoDiehl

Top Contributor
Mal von der ganzen "ist das sinnvoll"-Diskussion abgesehen solltest du zuerst versuchen deinen Java-Code zu optimieren:
- JDBC-Treiber laden muss man nur einmal pro VM machen
- Du erzeugst auch pro Thread eine neue DB-Verbindung. Das halte ich ebenfalls für übertrieben und anfällig

Du könntest, ebenso wie du einmal die VM anlegst, einmal die DB-Verbindung einrichten und die für alle Threads verwendet.
Ob es die konkreten Fehlermeldungen behebt weiß ich nicht. So rum habe ich auch noch nicht JNI benutzt, daher keine Ahnung...
 

tfa

Top Contributor
Einerseits soll das C++-Programm in Java programmiert werden können. Anderseits kann ich nicht auf Anhieb das komplette C++-Ökosystem in Java abbilden, sodass ich dann an noch kritischen Stellen die JVM über C++ benutzen möchte.

An deiner Stelle würde ich das vernünftig in Java machen, ohne JNI-Verrenkungen und Legacy-Code. Wenn das Altsystem nicht komplett und auf einmal abgelöst werden kann, halte es so lange am Leben, wie es nötig ist. Das irgenwie zurecht zu frickeln führt schnell in die Katastrophe.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
D Linux, Java-Version wird nicht erkannt bzw. welche Einstellung fehlt noch? Allgemeine Java-Themen 19
M Eclipse unter Linux Lite Allgemeine Java-Themen 2
M priority scheduling in Linux Allgemeine Java-Themen 3
Killunox MaxHeap Zuweisung unter Linux funktioniert nicht Allgemeine Java-Themen 1
L Super User via Processbuilder (Linux) Allgemeine Java-Themen 3
OSchriever Linux-Programm öffnen Allgemeine Java-Themen 6
OSchriever Programm über Linux-Kommandozeile ausführen Allgemeine Java-Themen 20
J Linux .jar beim Start automatisch ausführen Allgemeine Java-Themen 6
J ASCM - In Linux öffnen Allgemeine Java-Themen 3
L Tesseract-OCR 4.0 unter Linux funktioniert nicht Allgemeine Java-Themen 3
J Sound mit Clip in Linux abspielen Allgemeine Java-Themen 3
K USB infos unter Linux abfragen? Allgemeine Java-Themen 2
N Lizenzensierung von Java Programmen unter Linux Allgemeine Java-Themen 3
P OneWire Java Linux Allgemeine Java-Themen 11
R probleme beim starten von jar unter linux Allgemeine Java-Themen 2
A Linux bash script ausführen Allgemeine Java-Themen 16
C Windows RCP Application unter Linux bauen lassen Allgemeine Java-Themen 3
D jnativehook auf Linux Allgemeine Java-Themen 1
A Linux: Native Library mit Rootrechten ohne Prozess mit sudo zu starten Allgemeine Java-Themen 1
F Linux & NetBeans: Datei in Systemverzeichnis schreiben? Allgemeine Java-Themen 1
E Sonderzeichen nicht setzbar: Großes Problem bei Programmierung unter Linux Mint mit Virtual Box Allgemeine Java-Themen 5
F URI Schema in Linux erstellen? Allgemeine Java-Themen 3
D Problem VLC4J Raspbian(Linux) Allgemeine Java-Themen 0
M Code läuft unter windows aber nicht unter Linux Allgemeine Java-Themen 6
F.S.WhiTeY JDK installieren Linux: Nach Update link auf Java zerschossen Allgemeine Java-Themen 4
M Java auf Linux und Windows Allgemeine Java-Themen 6
D pfad zur jre linux Allgemeine Java-Themen 8
B Ordner öffnen mittels Java in Linux-Umgebung Allgemeine Java-Themen 7
P Eclipse Unter Windows erstelle .jar unter Linux (Ubuntu) funktioniert nicht Allgemeine Java-Themen 5
G Runtime.exec beendet Programm unter Linux, wenn Java Programm beendet wird Allgemeine Java-Themen 3
G RXTX native library unter Linux in jar build angeben Allgemeine Java-Themen 4
R Umlautproblem unter Linux Allgemeine Java-Themen 10
Gossi Mit Java auf Linux- & Windowssysteme zugreifen? Allgemeine Java-Themen 4
T Jar File läuft unter Windows aber nicht unter linux Allgemeine Java-Themen 10
Z Probleme bei Stringvergleichen (Windows/Linux) Allgemeine Java-Themen 10
M Linux Rechner per ssh runterfahren mit Java Allgemeine Java-Themen 8
F Process.getInputStream unter Linux Allgemeine Java-Themen 7
J Java programm lässt sich in win7 nach linux install nicht mehr ausführen Allgemeine Java-Themen 18
G Input/Output URLDecoder.decode - Unterschiedliche Ergebnisse Windows / Linux Allgemeine Java-Themen 2
G Java und Syslog (Linux) Allgemeine Java-Themen 3
T Javaprogramm unter Linux auf bestimmten Kern starten/laufen lassen ? Allgemeine Java-Themen 22
D Unix/Linux Benutzer-Authentifikation über Java Allgemeine Java-Themen 3
B JNA, Linux und die Smart Card Allgemeine Java-Themen 2
P Runnable Jar File über Windows ausführbar doch über Linux nicht Allgemeine Java-Themen 8
C RXTX Treiber einbinden für Linux Allgemeine Java-Themen 6
C Datei auslesen wie unter Linux mit "tail -f" Allgemeine Java-Themen 3
E Linux Cups Allgemeine Java-Themen 6
S Verhalten von System.getenv() in Ubuntu / Linux Allgemeine Java-Themen 12
T linux problem mit Desktop.getDesktop().open(..) Allgemeine Java-Themen 5
lordcarlos Runtime exec und mplayer (linux) Allgemeine Java-Themen 11
J dialogys unter linux Allgemeine Java-Themen 4
S Problem beim Drucken auf Netzwerkdrucker unter Linux Allgemeine Java-Themen 9
B Linux: Bash von Java aus aufrufen Allgemeine Java-Themen 10
T System Preferences + LInux (Ubuntu) Allgemeine Java-Themen 8
R Timing-Problem (?) Linux versus Windows Allgemeine Java-Themen 13
F Document öffnen unter Linux Allgemeine Java-Themen 4
F Portzugriffe Java @Linux & Windows? Allgemeine Java-Themen 4
W Deployment unter Linux Allgemeine Java-Themen 17
D Mit Linux mehrere Kommandos in einem Subprozeß Allgemeine Java-Themen 3
E Erfahrung mit RXTX sowie Windows und Linux Allgemeine Java-Themen 9
J Externes Programm starten und stoppen (Linux) Allgemeine Java-Themen 3
B Programm läuft unter Linux, aber nicht unter Windows Allgemeine Java-Themen 3
J UTF-8 Sockets : Windows<->Linux Ein altes Problem Allgemeine Java-Themen 7
S Ausführbare Scriptdatei unter Linux erstellen Allgemeine Java-Themen 6
J Programm unter Linux starten Allgemeine Java-Themen 3
R Jar-File vom Linux Desktop durch ancklicken starten? Allgemeine Java-Themen 5
P Linux port Allgemeine Java-Themen 4
P CLASSPATH LINUX Allgemeine Java-Themen 9
L Programm läßt sich wegen Java unter Linux nicht starten Allgemeine Java-Themen 4
V JAR-File läuft unter Windows und Linux, aber nicht unter OSX Allgemeine Java-Themen 6
M Welches Linux zum Java testen? Allgemeine Java-Themen 5
D linux shell aus java öffnen Allgemeine Java-Themen 5
A Linux-Consolenbefehle über Java ausführen? Allgemeine Java-Themen 2
B Java Applikation incl. dll unter Linux ausführen? Allgemeine Java-Themen 11
G Java Socket langsam unter Linux Allgemeine Java-Themen 21
T *.jar applikationen auf Linux installieren Allgemeine Java-Themen 4
P jdic/Linux Allgemeine Java-Themen 2
G Linux Dateinamen Charset Probleme Allgemeine Java-Themen 8
Ark Linux: Shell-Skript zum Kompileren und Starten Allgemeine Java-Themen 4
N Linux-Commands über Java Anwendung ausführen Allgemeine Java-Themen 12
M Eigenes Java-Server-Programm unter Linux steuern? Allgemeine Java-Themen 13
P linux + java :/ Allgemeine Java-Themen 11
G Läuft nicht unter Linux oO Allgemeine Java-Themen 10
S Java Entwicklungsumgebungen unter XP und Linux und weitere F Allgemeine Java-Themen 7
W Programm starten unter Linux Allgemeine Java-Themen 10
M Speicherverwaltung unter Linux Allgemeine Java-Themen 7
A Geschwindigkeit Java unter Linux Allgemeine Java-Themen 9
J jdic funktioniert unter Linux nicht Allgemeine Java-Themen 18
S Welche Javaversion ist in meinem Linux? Allgemeine Java-Themen 2
L Native Threads unter Linux? Allgemeine Java-Themen 2
V JVM OutofMemory Linux geht, windows nicht Allgemeine Java-Themen 3
L mit exec() befehl ausführen ( OS X / Linux) Allgemeine Java-Themen 8
B JMF -> Webcam (Linux) Allgemeine Java-Themen 14
B Java 6 unter Ubuntu (Linux) Allgemeine Java-Themen 4
B gibVerzeichnis() unter linux Allgemeine Java-Themen 9
D JMF unter Linux/Windows, nichts funktioniert Allgemeine Java-Themen 3
F Runtime.getRuntime().exec mit Linux und Leerzeichen Allgemeine Java-Themen 3
L javax.comm unter Linux Allgemeine Java-Themen 11
G Zugriff von Windows auf Linux Allgemeine Java-Themen 11
M Wie mit Dateipfaden zwischen Linux und WIndows hantieren? Allgemeine Java-Themen 2

Ähnliche Java Themen

Neue Themen


Oben