Reputation: 51
I am currently looking under the hood of the JVM, of the OpenJDK JVM to be speciffic. And I was wondering how the JVM calls native functions. I know that it loads them dynamically and saves them as void*
but I can't seem to find the actual calling part.
For example:
jint Java_Test_add(jobject*, jint);
can be a native c function but so can:
jvoid Java_Test_main(jobject*);
So now I was wondering how the JVM can call these functions when only having the method signature as a string at runtime. As far as I know C does not support such dynamic calls. I hope someone can tell me how this works or how to approach such an problem.
Thanks in advance!
Upvotes: 1
Views: 461
Reputation: 19821
Each language has its own set of procedure calling conventions (how a call to a subroutine is performed, what should be put in the stack or in registers, what must be done to return from a subroutine) and what happens in a case like this, calling from Java a native method written in C, is that the jvm will need to mimic the C calling convention to execute, outside from its normal context, the method Java_Test_add
that you wrote.
The method signature will be used to get a reference to the C function location in memory (loaded from the static library you link when you compile your project) and the invoke_native instruction implementation (different for each jvm implementation) will take care of performing the call and handle the return (this can be done manually but as someone already said, there are libraries like libffi that implement various calling conventions).
So, you don't have to look at this from the point of view of the C language features, because yes, the language does not provide facilities of some easy syntactic sugar to perform this kind of "dynamic" calls at runtime, but this can still be implemented, eventually adding a bit of assembly to the mix.
Upvotes: 0
Reputation: 98350
C does not support such dynamic calls
Actually it does. Dynamic libraries are called dynamic, because they can be loaded at run-time, and their code can be linked by a symbolic name.
DLL (or shared library in Unix terminology) usually contains a symbol table used to map a symbolic name to an address of a function. OS provides API to resolve an address by a name, e.g. dlsym
in POSIX or GetProcAddress
on Windows.
JVM basically uses this API to find a function address on the first call of a native method. Then it remembers the resolved address, so that later invocations are done directly via this address.
The alternative way to bind a native method to a function address is to call RegisterNatives
JNI function. A caller provides the direct pointer to a native function, not necessarily named according to standard JNI naming convention.
That's how native method linking works. The procedure of calling native method is described here.
Upvotes: 1
Reputation: 88721
You can solve this in one of two basic ways:
Upvotes: 0