Proposal: Use new JDK_EXPORT decorator instead of JNIEXPORT

Magnus Ihse Bursie magnus.ihse.bursie at
Tue Dec 11 14:34:51 UTC 2018

On 2018-12-11 00:23, David Holmes wrote:
> Hi Magnus,
> On 10/12/2018 11:19 pm, Magnus Ihse Bursie wrote:
>> I propose that we introduce a new define, available to all JDK native 
>> files (Hotspot included), called JDK_EXPORT. The behavior of this 
>> symbol will be very similar (as of now, in fact identical) to 
>> JNIEXPORT; however, the semantics will not.
>> Currently, we "mis-use" the JNIEXPORT define to mark a function for 
>> exporting from the library. The problem with this is that JNIEXPORT 
>> is part of the JNI interface, and is supposed to be used when C 
>> programs interact with Java. And, when doing this, the function 
>> should be fully decorated like this: "JNIEXPORT foo JNICALL".
> I've seen a lot of the emails on this issue and I don't fully 
> understand what has been going wrong. But the intent is obviously the 
> JNIEXPORT represents what is needed to export this function for use by 
> JNI, while JNICALL defines the calling convention. I agree there may 
> be some mistmatch when functions are actually not intended for general 
> export outside the JDK but are only for internal JDK use.
>> We do have many such JNI exports in our native libraries, but we also 
>> have a lot of other, non-JNI exports, where one native library just 
>> provides an interface to other libraries. In these cases, we have 
>> still used JNIEXPORT for the functionality of getting the function 
>> exported, but we have not been consistent in our use of JNICALL. This 
>> has caused us way too much trouble for something that should Just 
>> Work<tm>.
> Are you suggesting that the interface between different libraries in 
> the JDK should not be a JNI interface? Is this because you think the 
> functions in these libraries are only for JDK internal use or ... ??
>> I therefore propose that we define "JDK_EXPORT", with the same 
>> behavior as JNIEXPORT (that is, flagging the function for external 
>> visibility in the resulting native library), but which is *not* 
>> supposed to be exported to Java code using JNI, nor supposed to be 
>> decorated with 
> Just a clarification there. JNI functions are not exported to Java 
> code, they are exported to native code. Java code can declare native 
> methods and those native methods must be written as JNI functions, but 
> that's not what we are discussing. Libraries expose a JNI interface (a 
> set of functions in the library) that can be called by application 
> native code, using JNI.
We're apparently looking at "JNI" and "exporting" from two opposite 
sides here. :-) Just to make everything clear: If I have a Java class
class MyClass {
   public static void native myNativeFunc();

then I have one half of the JNI function, the Java half. This must be 
matched by a corresponding implementation in native, like this:
Java_MyClass_myNativeFunc(void) {
// ... do stuff

And this is the native half of the JNI function. Right? Let's leave 
aside which side is "exporting" to the other for now. :-)

This way of setting up native functions that can be called from Java is 
what I refer to as JNI. And when you declare a native JNI function, you 
*must* use both JNIEXPORT and JNICALL. Alright?

We do have a lot of those functions in our native libraries. And they 
are correct just the way they are.

However, we also have *other* native functions, that are exported, not 
as JNI functions that should be called from Java, but as normal native 
library functions that should be called by other native code. Okay so 
far? And *those* functions have been problematic in how we decorate 
them. My proposal is that we *refrain* from using JNIEXPORT for those 
functions, and instead use JDK_EXPORT as name for the macro that 
decorates them as exported. That way, we can clearly see that a function 
like this:

JLI_ReadEnv(char* env);

is correctly declared, and will be exported to other native libraries, 
but not to Java.

Just to clarify, this has nothing to do with if this is a officially 
supported API or not. In general though, I assume that most (if not 
all?) of our exported functions (apart from the JNI_* stuff) is supposed 
to be consumed by other libraries in the JDK, and is not a public API.


>> JNICALL. All current instances of JNIEXPORT which is not pure JNI 
>> native functions should be changed to use JDK_EXPORT instead.
>> I further propose that this macro should reside in a new file 
>> "jdk.h", placed in the new directory 
>> src/java.base/share/native/include/internal. This header file path 
>> will automatically be provided to all native libraries, but not 
>> copied to the JDK being built. (The existence of a "include/internal" 
>> directory with this behavior has been discussed before. There are 
>> more files that ought to be moved there, if/when it is created.) I 
>> believe in many cases the #include "jni.h" can be just modified to 
>> #include "#jdk.h", since most native code will not require "jni.h" 
>> unless actually doing JNI calls -- most have included this file to 
>> get the JNIEXPORT macro, which would explain the pervasive use of 
>> #include "jni.h" in our code base.
> jni.h also defines all of the types used by the JNI. Those types are 
> pervsive to the native code used throughout the JDK.
>> Thoughts?
> I think we need to understand the problems on Windows that prompted 
> all this. Then I think we need to look at exactly how jni.h and 
> JNIEXPORT etc are being used and understand whether this is truly an 
> exported interface or not.
> Cheers,
> David
>> /Magnus

More information about the core-libs-dev mailing list