# Mit JNI von C++ auf ein laufendes Java-Programm zugreifen



## tec1 (21. Nov 2009)

Hallo Leute,

ich habe folgendes Problem.

Ich greife von einem C++-Programm auf ein Java-Programm zu, über JNI. Das klappt schon mal sehr gut. Mein Problem ist aber, dass in meinen Java-Programm ein bestimmter Teil ziemlich zeitaufwändig ist, das starten der BIRT-Reportengine. Ich will hier aber nicht auf die Eigenheiten von BIRT eingehen sondern ganz allgemein fragen. 

Wie kann ich mit einem JNI Aufruf aus C++ z.B. ein Java-Objekt erzeugen, evtl. ein Singleton, und dann mit später folgenden JNI Aufrufen aus C++ dieses bereits erzeugte Objekt verwenden? Ich möchte keinen Application-Server wie z.B. Tomcat verwenden um z.B. Servlets laufen zu lassen oder Webservices aufzurufen. 

Kann ich nicht ein Java-Programm über JNI starten und dann später wieder mit JNI auf ein bereits laufendes Java-Programm zugreifen? Sollte doch gehen, blos wie?


----------



## Marco13 (22. Nov 2009)

Beschreib vielleicht mal genauer, warum das, was du suchst, vermutlich nicht The Invocation API ist...


----------



## tec1 (22. Nov 2009)

Hallo Marco,

genau mit der Invocation-API habe ich vor zu arbeiten, sie gehört ja auch zum JNI, oder? Ein paar einfache Testfälle habe ich schon erfolgreich implementiert.

Was ich vorhabe ist folgendes: 

1. Ich starte aus meiner C++ Applikation ein Java-Programm, welches für unbestimmte Zeit laufen soll.
2. Zu einem späteren Zeitpunkt will ich aus meiner C++ Applikation dieses laufende Java-Programm direkt ansprechen.

Geht das prinzipiell überhaupt, ohne dass ich mit einem Server, wie z.B. Tomcat, arbeiten muss?
Wenn es geht wie würdet ihr das realisieren?

Viele Grüße


----------



## faetzminator (22. Nov 2009)

Sockets, stdio, Pipes (zumindest unter Linux), ...


----------



## Spacerat (22. Nov 2009)

faetzminator hat gesagt.:


> Pipes...


Klar... PipedInputOutputStreams... Da dieses Javaklassen sind, gibt es wohl kaum Probleme, diese auch auf JNI-Seite zu instanzieren. Auf jeder Seite jeweils ein Input- sowie ein OutputStream... fertig ist der Direkte Messageport. Aber ich glaube fast, das geht auch einfacher. Z.B. mit Heap-Buffern aus dem Paket [c]java.nio[/c].


----------



## tec1 (22. Nov 2009)

Hallo,

habt ihr mal ein einfaches Beispiel wie ich jetzt das laufende Java-Programm anspreche? Das würde mir wirklich helfen. Auch ein Beispiel ohne JNI wäre toll. Z.B. so:

1. Ich starte ein Java-Programm, welches für unbestimmte Zeit läuft.
2. Ich starte ein zweites Java-Programm, welches das erste Programm direkt anspricht.

Viele Grüße


----------



## Spacerat (22. Nov 2009)

Also konkrete Beispiele sind da iwie immer recht aufwändig. Eine steht jedoch fest: Zwei Javaprogramme können entweder nur über Netzwerk (eben Sockets usw.) oder aufwändig per JNI programmierte Messageports kommunizieren. Ersteres funktioniert sogar ohne JNI und letzeres ist im Zeitalter der Loop-Network-Adapter gar nicht mehr zeitgemäss.


----------



## Gastredner (22. Nov 2009)

Im Java-Blogbuch gibt es ein Tutorial zum Erstellen einer Anwendung, deren einzelne Instanzen miteinander kommunizieren können:
Java Blog Buch : D) Java-Anwendung nur einmal ausführen
Sollte man ja auf zwei verschiedene Anwendungen anpassen können.


----------



## Spacerat (22. Nov 2009)

Hm? ServerSocket? Gelesen?
Du hast natürlich Recht. So fängt die Story von der wir hier reden eigentlich auch an. Nur dass die ServerSocket nicht nur einfach einen Port belegt, sondern auch auf Kommunikation wartet. Kommunikation von einer Anwendung, die diesen Port nicht öffnen konnte.
@Edit: Steht im übrigen auch im Beispiel dort. Wenn man so ca. bis zum 3. oder 4. gekommen ist.


----------



## tec1 (22. Nov 2009)

Gut, ich schaue mir dann morgen mal die Sockets an und experimentiere ein wenig, vielen Dank schonmal für eure Tipps.


----------



## tec1 (25. Nov 2009)

Ich habe das jetzt nit einem Java ServerSocket realisiert, welcher dann von der C++ Applikation aus mit QTCPSocket's angesprochen wird. Anbei mal der Code für den Java ServerSocket. Für Anmerkungen/Anregungen bin ich jederzeit zu haben. Ansonsten Dank an alle die mir wertvolle Tipps gegeben haben.


```
public class BirtReportServer {

    private static final Logger log = Logger.getLogger(BirtReportServer.class);
    private ServerSocket _server;
    private EngineConfig _engineConfig;
    private int _nCountOfRequests;

    public BirtReportServer() throws IOException
    {
	_nCountOfRequests = 0;
    }

    public void startAndRunServer(int nPort, Map<String, String> startParams) throws Exception
    {
	log.debug("start");

	try
	{
	    try
	    {
		_server = new ServerSocket(nPort);
		log.debug("ServerSocket started successfully");
		_engineConfig = BIRTReportManager.createEngineConfig(startParams);
		Platform.startup(_engineConfig);
		log.debug("after Platform.startup");
	    }
	    catch (IOException e1)
	    {
		log.error("start of server failed", e1);
	    }

	    while (true)
	    {
		try
		{
		    Socket client = _server.accept();
		    _nCountOfRequests++;
		    log.debug("accept: count of requests=" + _nCountOfRequests);

		    BufferedReader input = new BufferedReader(new InputStreamReader(client.getInputStream()));
		    PrintWriter output = new PrintWriter(client.getOutputStream());

		    List<String> liInputParams = new ArrayList<String>();
		    String line;
		    log.debug("log input arguments:");
		    int nIndex = 0;
		    while ((line = input.readLine()) != null)
		    {
			if (line.length() == 0)
			    break;

			StartParameterUtils.logArguments(nIndex, line);

			liInputParams.add(line);
			nIndex++;
		    }

		    ParameterMap parameterMap = new ParameterMap();
		    StartParameterUtils.fillStartParameterMap(liInputParams.toArray(new String[liInputParams.size()]), parameterMap);

		    // create report
		    if (!parameterMap.getStartParams().containsKey(StartParameter.shutDownBirtServer))
		    {
			// validate parameterMap
			StartParameterUtils.validateStartParameterMap(parameterMap, true);

			BIRTReportManager reportManager = new BIRTReportManager();
			reportManager.createReportOutput(parameterMap, _engineConfig);

			output.write("ok");
			output.flush();
		    }
		    // shut down server
		    else
		    {
			// leave while loop and shut down Platform in finally area
			break;
		    }

		    input.close();
		    output.close();
		    log.debug("after input output close");
		}
		finally
		{

		}
	    }
	}
	finally
	{
	    log.debug("before shutdown");
	    _server.close();
	    Platform.shutdown();
	    log.debug("after shut down BIRT platform");
	}
    }

}
```


----------

