Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the SIZE constant only @Native for Integer and Long?

Tags:

java

java-8

I understand the use of the @Native annotation.

Indicates that a field defining a constant value may be referenced from native code. The annotation may be used as a hint by tools that generate native header files to determine whether a header file is required, and if so, what declarations it should contain.

However, while reading the java source code I noticed that in the class Integer and Long the SIZE constant is @Native while it is not for the Float, Byte, Double, Short and Character.

Note that the SIZE constant represents the number of bits used to represent the actual value.

public static final int SIZE = 8;//Byte
public static final int SIZE = 16;//Character
public static final int SIZE = 16;//Short
public static final int SIZE = 32;//Float
@Native public static final int SIZE = 32;//Integer
@Native public static final int SIZE = 64;//Long
public static final int SIZE = 64;//Double

Edit : I just noticed that this also applies for MAX_VALUE and MIN_VALUE of the same classes.


Edit 2 : I had spare time to do some research on this, and looking at the header files of the Long, Float etc. classes I had hope to figure out that the constants were not present in the other headers, but unfortunately they are.

static const jint SIZE = 8L;//java/lang/Byte.h
static const jint SIZE = 16L;//java/lang/Character.h
static const jint SIZE = 16L;//java/lang/Short.h
static const jint SIZE = 32L;//java/lang/Float.h
static const jint SIZE = 32L;//java/lang/Integer.h
static const jint SIZE = 64L;//java/lang/Double.h
static const jint SIZE = 64L;//java/lang/Long.h

Why is the SIZE constant only @Native for Integer and Long ?

like image 349
Jean-François Savard Avatar asked Feb 27 '15 17:02

Jean-François Savard


3 Answers

TLDR: Jump to the conclusion


Why is the SIZE constant only @Native for Integer and Long?

A brief history of @Native

I made some search on the mailing lists. I found some interesting things.

At first an annotation (1 2) javax.tools.annotation.ForceNativeHeader was introduced to

to trigger javah on a class.

It is used by com.sun.tools.javac.processing.NativeapiVisitor. By looking at the code we can see that the native header is generated if the class declare some native methods or if the class is annotated @ForceNativeHeader.

Later this annotation was renamed to GenerateNativeHeader (1 2).

Then this annotation was added to several types (especially Integer and Long) with an interresting comment:

/* No native methods here, but the constants are needed in the supporting JNI code */
@GenerateNativeHeader
public final class Long extends Number implements Comparable<Long> {...

But by adding this annotation it add a problematic dependency from base module to the module containing javax.tools. So the annotation were removed from Integer and Long and these files were explicitly added to the build process since the header were no more automatically generated... a "(hopefully temporary) hack".

So a new annotation java.lang.annotation.Native was created and used in Integer and Long. The annotation was set a TargetType FIELD.

the annotation should be directly applied to the constant fields that need to be exported -- and not to the class as a whole.


All the purpose of this stuff is:

javac could generate native headers for classes containing native methods.

It is the case of Integer and Long

this was a part of the JEP 139: Enhance javac to Improve Build Speed:

javah will be automatically run on any class that contains native methods and the generated C-headers will be put in the (-h) headerdir. A new annotation @ForceNativeHeader is used for classes that have final static primitives that need to be exported to JNI, but no native methods.


A basic experimentation

I made a basic experimentation on the JDK. I clone the open-jdk forest and i successfully build it. As expected the header files where generated for Integer and Long (thanks to @Native) and for Float and Double (thanks to their native methods) but not for Byte, Short...

    ls -l build/macosx-x86_64-normal-server-release/support/headers/java.base/java_lang_*
    ...
    java_lang_Double.h
    java_lang_Float.h
    java_lang_Integer.h
    java_lang_Long.h
    java_lang_Object.h
    java_lang_Package.h
    ...
    

Then i tried to remove the @Native from the Integer fields and i tried to build again the jdk but i get an error:

jdk/src/java.base/unix/native/libnio/ch/FileChannelImpl.c:35:10: fatal error: 'java_lang_Integer.h' file not found
#include "java_lang_Integer.h"
         ^
1 error generated.

logically since the header have not been generated.

I have also confirmed that java_lang_Integer.h is included in several c and cpp files:

find .  \( -name "*.c" -o -name "*.cpp" \) -exec grep "java_lang_Integer.h" {} \; -print
#include "java_lang_Integer.h"
./jdk/src/java.base/unix/native/libnio/ch/FileChannelImpl.c
#include "java_lang_Integer.h"
./jdk/src/java.base/unix/native/libnio/ch/IOUtil.c
#include "java_lang_Integer.h"
./jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c
#include "java_lang_Integer.h"
./jdk/src/java.base/windows/native/libnio/ch/FileChannelImpl.c
#include <java_lang_Integer.h>
./jdk/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp

like Long

find .  \( -name "*.c" -o -name "*.cpp" \) -exec grep "java_lang_Long.h" {} \; -print
#include "java_lang_Long.h"
./jdk/src/java.base/unix/native/libnio/ch/FileDispatcherImpl.c

like Float

find .  \( -name "*.c" -o -name "*.cpp" \) -exec grep "java_lang_Float.h" {} \; -print
#include "java_lang_Float.h"
./jdk/src/java.base/share/native/libjava/Float.c
#include "java_lang_Float.h"
./jdk/src/java.base/share/native/libjava/ObjectInputStream.c
#include "java_lang_Float.h"
./jdk/src/java.base/share/native/libjava/ObjectOutputStream.c

and like Double

find .  \( -name "*.c" -o -name "*.cpp" \) -exec grep "java_lang_Double.h" {} \; -print
#include "java_lang_Double.h"
./jdk/src/java.base/share/native/libjava/Double.c
#include "java_lang_Double.h"
./jdk/src/java.base/share/native/libjava/ObjectInputStream.c
#include "java_lang_Double.h"
./jdk/src/java.base/share/native/libjava/ObjectOutputStream.c

but neither Short

find .  \( -name "*.c" -o -name "*.cpp" \) -exec grep "java_lang_Short.h" {} \; -print

nor Byte, nor Character.


Conclusion

Among all these types, only Integer, Long, Float, Double are used in the native source code of the jdk.

And only the Integer and Long fields are annotated with @Native because they have no native methods (as opposed to Float and Double)

like image 181
gontard Avatar answered Nov 06 '22 16:11

gontard


gontard got it right.

javac will (optionally) generate a native header file if a class contains native methods or fields annotated with @Native.

This was a new feature for javac in JDK 8, and is nothing to do with the Jigsaw module system, as some have conjectured. The JDK build system notes when javac has generated new/different native header files, and uses that to only trigger recompilation of native code when necessary.

Jonathan Gibbons, Oracle's javac team

like image 20
Jonathan Gibbons Avatar answered Nov 06 '22 16:11

Jonathan Gibbons


Looking at the issue and fix, it looks like this has been done to resolve a handling of a header file generation for special classes in jigsaw

Jigsaw is a module system designated to use in Java SE Platform and JDK. More details here

Here is a corresponding changeset. You can see a comment,

Special handling of header file generation for classes in the jigsaw base module which currently can't add the annotaion GenerateNativeHeaders. For these specific classes the java file and the class have the same names which enables shortcutting the dependencies.

From the changeset I see that for the sake of purpose in addition tojava.lang.Integer and java.lang.Long , also some properties in java.net.SocketOptions, sun.nio.ch.IOStatus, java.io.FileSystem have been changed to @Native.

So I assume only those were needed to solve the dependency with jigsaw.

like image 2
vtor Avatar answered Nov 06 '22 16:11

vtor