September 30, 2011

huckfinn huckfinn
Lab Rat
93 posts

[Solved] Independant Threads with separate CommandLine

Page  
1

Hello,

I have a main Qt-Thread (main.exe), which in turn starts an executable jar via JNI (lets say external.jar).

This external.jar listens continuously on a special socket(localhost, PORT).
The expected message should be sent by the main.exe, which is blocked by the Listening external.jar.

I would like to run that jar in a separate thread, and if possible with a separate cmd.exe.

  1. #include <jni.h>
  2. #include "ExternJar.h"
  3.  
  4. #pragma comment (lib,"C:\\Program Files\\Java\\jdk1.6.0_26\\lib\\jvm.lib")
  5.  
  6. /// Constructor
  7. ExternJar::ExternJar(const char* pPathToJar, const char* pPathToLib, const char *t_argv, const char *t_path2Package, const char* t_methodName)
  8. {
  9.    int oi = 0;
  10.    options[oi++].optionString = const_cast<char*>(pPathToJar);
  11.    vm_args.nOptions = oi;
  12.    vm_args.version = JNI_VERSION_1_6;
  13.    vm_args.options = options;
  14.    vm_args.ignoreUnrecognized = JNI_FALSE;
  15.  
  16.    argumentString = t_argv;
  17.    path2Jar = pPathToJar;
  18.    path2Lib = pPathToLib;
  19.    packagePath = t_path2Package;
  20.    methodName = t_methodName;
  21.    debugMode = 0;
  22. }
  23.  
  24. void ExternJar::setClassName()
  25. {  
  26.    switch(JNI_CreateJavaVM( &jvm,(void **)&env, &vm_args)) {
  27.       case JNI_OK:
  28.          printf("\nJVM created --> Ready ...\n");
  29.    }
  30.    if( NULL == (cls = env->FindClass(packagePath)) ) printf("\nCan't find class %s\n", packagePath);
  31.    else printf("\nClass %s found!\n", packagePath);
  32. }
  33.  
  34. void ExternJar::setArgCV()
  35. {
  36.    if (!argumentString) return;
  37.    this->applicationArg0 = env->NewStringUTF(argumentString);
  38.    this->applicationArgs = env->NewObjectArray(1, env->FindClass("java/lang/String"), applicationArg0);
  39.    env->SetObjectArrayElement(applicationArgs, 0, applicationArg0);
  40. }
  41.  
  42. void ExternJar::setMethodName()
  43. {
  44.    mid = env->GetStaticMethodID(cls, methodName, "([Ljava/lang/String;)V");
  45.    printf("\nMethod name set to: %s", methodName);
  46. }
  47.  
  48. void ExternJar::callXMethod()
  49. {      
  50.    printf("\nCall now \n%s(\"%s\"):", methodName, argumentString);  
  51.    if (mid != NULL) env->CallStaticVoidMethod(cls, mid, applicationArgs);
  52.    else printf("\nMethod %s corrupted!\n", mid);
  53. }
  54.  
  55. JavaVM * ExternJar::getVM()
  56. {
  57.    return this->jvm;
  58. }
  59.  
  60. void * ExternJar::getEnv()
  61. {
  62.    return this->env;
  63. }
  64.  
  65. bool ExternJar::destroyVM()
  66. {
  67.    printf("\nDestroy VM now!");
  68.    if ( this->getVM()->DestroyJavaVM() == 1 ) return true;
  69.    else return false;
  70. }
  71.  
  72. void ExternJar::run()
  73. {
  74.    this->setClassName();
  75.    this->setArgCV();
  76.    this->setMethodName();
  77.    this->callXMethod();  
  78.    exec();
  79. }

I have Q_OBJECT set in the Header, it derives from QThread. I have a run() Method which also has a exec()… What else?
Thank you for any hints.

Cheers Huck

17 replies

October 1, 2011

Volker Volker
Ant Farmer
5428 posts

Why don’t you start the executable using QProcess? This gives you an asynchronous for free.

October 2, 2011

fluca1978 fluca1978
Lab Rat
529 posts

But if you want to run with another cmd.exe why don’t you use your main as a wrapper for the java process and then use QProcess to start such main?

October 4, 2011

huckfinn huckfinn
Lab Rat
93 posts

I wonder If can run that in a separate shell?

  1.  
  2. QString program = "C:\\Program Files\\Java\\jdk1.7.0\\bin\\java.exe";
  3. QStringList arguments;
  4. arguments << "-jar" << "C:\\Project\\dist\\Project.jar" << "-m" << "module.db" << "-i" << "K;1076076896,1076076882" ;  
  5. QProcess *myProcess = new QProcess();
  6. myProcess->start(program, arguments);

What can I search for, when I want to use the wrapper possibility?

October 4, 2011

Volker Volker
Ant Farmer
5428 posts

First:
Don’t use backslashes for the program path, use forward slashes. Qt will do the translation transparently.

Second:
Why do you want to involve a shell? It will do nothing else than calling java.exe with your arguments! Does the code you presented not work?

October 4, 2011

huckfinn huckfinn
Lab Rat
93 posts

The code in my first post works, I can invoke my extarnal.jar from my Qt-Project.

But my external.jar continuously listens on the socket to a port, while the expected message is never being sent by my suspended Qt-Project.

Therefore I try to make run the external.jar indipendent.

October 4, 2011

Volker Volker
Ant Farmer
5428 posts

I meant the second snippet, using QProcess. Does that work?

October 4, 2011

huckfinn huckfinn
Lab Rat
93 posts

According to the TaskManager a java.exe appears just for 1-2 seconds and disappears, but the jar is not executed properly.

October 4, 2011

Volker Volker
Ant Farmer
5428 posts

And it does work from the command line itself? How about giving a complete path to your module.db – it’s very likely that it is not found by your java application.

October 4, 2011

huckfinn huckfinn
Lab Rat
93 posts

Yes, when I call “java -jar external.jar -m modules.db … “ it works.

I have catched in external.jar already if that modules.db file would not exist, it would throw an FileNotFound-Exception; but I’ll try it.

October 5, 2011

huckfinn huckfinn
Lab Rat
93 posts

Here I call another *.jar, Its a Server, which listens uninterrupted to a socket and prints status messages System.out.println(“Bla”) continously as well. This jar has an infinte while-loop and does not terminate..
SO when I start this, another cmd.exe opens and that output should be visible?

  1. void MyClass::runExternal()
  2. {
  3.  QString t_exe_name("java.exe");
  4.  QStringList t_exe_arguments;
  5.  t_exe_arguments << "-jar" << "C:/SD_Projectz/TestServer/dist/TestServer.jar";
  6.  
  7.  QProcess *myProcess = new QProcess(p_ToObject);
  8.  QString t_joined = t_exe_arguments.join(" ");
  9.  QString t_all = QString("%1 %2").arg(t_exe_name).arg(t_joined);
  10.  myProcess->start(t_all);
  11.  
  12.  printf("\nWAIT: %d", myProcess->pid());
  13. }

Each start() my pid() is changed, visible on my Parent command line window, but no other cmd.exe opens for this Process.

When p_ToObject (the parent) is deleted, my process is terminated as well, right?

October 5, 2011

Volker Volker
Ant Farmer
5428 posts

Why do you expect a cmd.exe running in case you start a java.exe?

October 5, 2011

huckfinn huckfinn
Lab Rat
93 posts

These *.jars have System.out.println(“kljdas”); so without any further cmd.exe nothing is visible?

Then the only way I recognize the running jar is the java.exe in the TaskManager?

And since the jar is running continuously, I would say my java.exe should not disappear?

October 5, 2011

Volker Volker
Ant Farmer
5428 posts

Your java.exe does not “disappear”. It has no user interface, so it runs in the background, where it belongs.

If you want to see the output of stdout or stderr, you should write a .bat file. Either this opens a cmd.exe automatically when run, or you have to give it as argument to cmd.exe.

October 5, 2011

Andre Andre
Robot Herder
6295 posts

Better yet: if you want to display the output, why not make your Qt application display it instead in some nicely integrated way? QProcess gives you access to the stdout and stderr outputs of the process, after all.

 Signature 

Looking for Qt developers to join our team @ i-Optics: https://qt-project.org/forums/viewthread/25393/

October 6, 2011

mrtc3 mrtc3
Lab Rat
23 posts

To start in a separate shell try to detach the Process. Then you have your own cmd.exe:

  1. myProcess->startDetached(prog_name, prog_arguments);

But then you have no access to its stdio..

hth!

 Signature 

There are 10 types. Those who understand binary and those who don’t .)

Page  
1

  ‹‹ Auto adjust size (width) of QDockWidget      Text improperly scaled in QLineEdit wrapped in a QGraphicsProxyWidget when QGraphicsView is scaled ››

You must log in to post a reply. Not a member yet? Register here!