开发者

Inline::Java conflicts with Parallel::ForkManager

I am having problem with calling both Parallel::ForkMa开发者_如何学编程nager and Inline::Java at the same time. Specifically, if I call the Inline::Java with the JNI => 1 option (which I have to), then the fork process doesn't come back to the parent. Here are the codes:

use Parallel::ForkManager;

##### Calling Inline::Java #####
use Inline Java => <<END, JNI => 1;

END
###### End of Inline::Java #####

my $pm = Parallel::ForkManager->new(2);
for my $i (0..1) {
    $pm->start and next;
    print "Inside process $i\n";
    $pm->finish;
}
$pm->wait_all_children;
print "Back to Parent.\n";

If I run this program, it goes into the child processes but never comes back to the parent. If I remove the 3 lines between the comments, it runs fine. If I change the JNI => 1 to JNI => 0 (not that I'm allowed to change that parameter for my purpose), then there is an error message of Lost connection with Java virtual machine at /usr/lib64/perl5/site_perl/5.8.8/x86_64-linux-thread-multi/Inline/Java.pm line 975.

Does anyone have a clue how to resolve the conflict? I also have to call the Inline::Java before the parallel process so using require after parallel is done is not an option. Thx!


Every child is talking over the same socket, which leads to the VM receiving jibberish.

You need to delay making a connection to the VM so that it's done in the children instead of it the parent.

You could move all thing Inline::Java-related into another module, then use require Child; (not use Child;) after start.

If you need to use Inline::Java before launching the child, do it in a different process.


Using forks with Inline::Java is going to be a problem. Your perl script needs to maintain a TCP connection with the JVM. When you fork a new process, the same file descriptors for communicating with the JVM are passed to the child process so the parent and all the child processes are using the same sockets. That won't work. You need to redesign your application.

One possibility (which you have already discounted) is to delay starting the JVM until after a fork, starting a new JVM in each child process.

Another approach is to forget about forking from Perl and to leverage Java's superior threading model to do parallelization. Design your Java code to perform its tasks in new threads, and start new threads from Perl:

my $java = ... entry point to JVM ...

for my $n (1 .. $num_threads) {
    $java->startNewThread(@inputs)
}
$java->waitForThreadsToFinish();
$result = $java->getResults();

Perl also has its own threading model (see threads and threads::shared). I doubt that Perl's threads will work for this problem, but it still might be worth a try.


Update: another possibility that is mentioned in the Inline::Java docs is to use a shared JVM. Invoke Inline::Java with the option SHARED_JVM => 1, and when a new child process starts, call Inline::Java::reconnect_JVM() from the child to make a fresh connection. The downsides of this approach are

  1. it keeps the JVM active after the program ends, so you have to remember to kill the JVM
  2. it is incompatible with the option JNI => 1, which might be a dealbreaker to the OP.
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜