node-java icon indicating copy to clipboard operation
node-java copied to clipboard

What are the best practices for creating a reusable module with node-java?

Open iamdoron opened this issue 9 years ago • 5 comments

when I'm trying to use two modules that require the java module, I get the following error as soon as the second module starts using the java module (for example, java.import)

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00000001063aa6f2, pid=48054, tid=2571
#
# JRE version: Java(TM) SE Runtime Environment (8.0_51-b16) (build 1.8.0_51-b16)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.51-b03 mixed mode bsd-amd64 compressed oops)
# Problematic frame:
# C  [nodejavabridge_bindings.node+0x1a6f2]  _Z20getSystemClassLoaderP7JNIEnv_+0x12
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# 

hs_err_pid48054.log.zip

#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#

I think it happens because two different 'instances' of the node 'java' module are being required by the 2 different modules. I use similar code to the example in the two modules.

iamdoron avatar May 31 '16 06:05 iamdoron

Can you try

# gdb --args node your-program.js
# run
# // keep pressing 'c' until crash
# where

This should give a better stack trace of where it's failing.

joeferner avatar May 31 '16 19:05 joeferner

after I get 'Thread 1 received signal SIGSEGV, Segmentation fault.'

(gdb) where
#0  0x00000001066c92b4 in ?? ()
#1  0x0000000000000246 in ?? ()
#2  0x00000001066c9160 in ?? ()
#3  0x00007fff5fbfe418 in ?? ()
#4  0x00007fff5fbfe3e0 in ?? ()
#5  0x00000001059e6a92 in VM_Version::get_processor_features() () from /Library/Java/JavaVirtualMachines/jdk1.8.0_51.jdk/Contents/Home/jre/lib/server/libjvm.dylib
Backtrace stopped: previous frame inner to this frame (corrupt stack?)

then I continue:

(gdb) where
#0  getSystemClassLoader (env=0x0) at ../src/utils.cpp:168
#1  0x00000001064a7933 in Java::createJVM(JavaVM_**, JNIEnv_**) ()
   from code/java/build/Release/nodejavabridge_bindings.node
#2  0x00000001064a0f99 in Java::findClassSync(Nan::FunctionCallbackInfo<v8::Value> const&) ()
   from code/java/build/Release/nodejavabridge_bindings.node
#3  0x00000001064a9653 in Nan::imp::FunctionCallbackWrapper(v8::FunctionCallbackInfo<v8::Value> const&) ()
   from code/java/build/Release/nodejavabridge_bindings.node
#4  0x00000001001614df in v8::internal::FunctionCallbackArguments::Call(void (*)(v8::FunctionCallbackInfo<v8::Value> const&)) ()
#5  0x0000000100189b44 in v8::internal::MaybeHandle<v8::internal::Object> v8::internal::HandleApiCallHelper<false>(v8::internal::Isolate*, v8::internal::(anonymous namespace)::BuiltinArguments<(v8::internal::BuiltinExtraArguments)1>&) ()
#6  0x000000010018c7ad in v8::internal::Builtin_HandleApiCall(int, v8::internal::Object**, v8::internal::Isolate*) ()
#7  0x00000505a1a0963b in ?? ()
#8  0x00000505a1a09581 in ?? ()
#9  0x00007fff5fbfeee0 in ?? ()
#10 0x00007fff5fbfefb8 in ?? ()
#11 0x00000505a21a11a3 in ?? ()
#12 0x0000393737acc861 in ?? ()
#13 0x00002ea26e322a71 in ?? ()
#14 0x00003237b5415c71 in ?? ()
#15 0x0000393737acc861 in ?? ()
#16 0x00001673fd5041b9 in ?? ()
... (just a lot of ?? () lines)
#64 0x0000000000000000 in ?? ()

I continue again, now I see the fatal error message

(gdb) where
#0  0x00007fff8438bf06 in vMultiDimensionalInterpolatedLookupTable_Planar16Q12_avx2 () from /usr/lib/system/libsystem_kernel.dylib
#1  0x00007fff8feb94ec in charsetToEncodings () from /usr/lib/system/libsystem_pthread.dylib
#2  0x0000000000000000 in ?? ()

so technically, two modules could use, for example, two different versions of node-java? (that's not the situation here, I'm just trying to understand)

iamdoron avatar May 31 '16 20:05 iamdoron

It is possible for two node-java modules to coexist in one node.js process, but practically speaking, it requires some extra effort. The main requirement is that the classpath must be fully set up with all the classes needed by both modules before either module makes any calls to java methods that trigger the JVM to be created. So if one module fully initializes itself, including some call that triggers JVM creation, then the other module won't be able to initialize. See https://github.com/joeferner/node-java#jvm-creation for some info about this.

You might be able to change the order of initialization to fix the problem. If you can figure out the full class path necessary for both modules, your app could set up the class path early in its initialization, before you do anything to initialize either of the two modules. Or, you might find that simply reversing the order that you initialize the two modules fixes the problem.

Be aware that you need to make sure that only one java module exists under your node_modules folder. If the two modules you use each require a specific but different version of java, then the npm installer won't dedupe them into one module. That too will result in code that tries to create two JVMs, which won't work.

You might find that it is very difficult to make the two modules coexist without making changes to those modules. You might want to start a conversation with the authors of those modules, and see if they can refactor their code to use the techniques described by https://github.com/joeferner/node-java#jvm-creation.

unitive-jim avatar May 31 '16 23:05 unitive-jim

iamdoron i fixed that bug in 0.7,2

egandro avatar Jun 14 '16 17:06 egandro

@iamdoron is this issue fixed, how did you get around it.

ramaguruprakash avatar Jul 21 '22 22:07 ramaguruprakash