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

I understand the use of @Native annotation.

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

However, while reading the java source code, I noticed that in the Integer and Long classes the constant is SIZE @Native , while this is not for 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 to MAX_VALUE and MIN_VALUE the same class.




Edit 2: I had some free time to do some research on this, and looking at the header files of the classes Long, Float, etc., I was hoping to find out that there were no constants in 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 integers and longs?

+42
java java-8
Feb 27 '15 at 17:24
source share
3 answers

TL; DR : transition to conclusion




Why is the SIZE constant only @Native for integers and longs?

A Brief History of @Native

I did a few searches on the mailing lists. I found interesting things.

First, annotation ( 1 2 ) javax.tools.annotation.ForceNativeHeader was introduced in

to call javah for the class.

Used by com.sun.tools.javac.processing.NativeapiVisitor . Looking at the code, we see that a custom header is generated if the class declares some of its own methods or the class is annotated by @ForceNativeHeader .

This annotation was later renamed GenerateNativeHeader ( 1 2 ).

This annotation is then added to several types (especially Integer and Long ) with an interesting 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, add the problematic dependency on the base module to the module containing javax.tools. Thus, the annotation was removed from Integer and Long , and these files were explicitly added to the build process , since the header is no longer generated automatically ... a "(hopefully temporary) hack" .

So a new annotation java.lang.annotation.Native was created and used in Integer and Long . Annotations were set as 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.




This whole goal is as follows:

javac can generate custom headers for classes that contain custom methods.

This is the case of Integer and Long

this was part of JEP 139: Enhance javac to improve build speed :

javah will automatically run in any class that contains its own methods, and the generated C-headers will be placed in the (-h) headerdir. The new @ForceNativeHeader annotation is used for classes with finite static primitives that need to be exported to JNI, but not using native methods.




Core experimentation

I conducted basic experiments on the JDK. I am cloning an open-jdk forest and I am successfully creating it. As expected, the header files generated for Integer and Long (thanks to @Native ) and for Float and Double (thanks to their own 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 @Native from the Integer fields, and I tried to create jdk again, 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 was not generated.

I also confirmed that java_lang_Integer.h 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 not Short

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

and Byte , not Character .




Conclusion

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

And only Integer and Long tags are annotated using @Native , as they have no built-in methods (unlike Float and Double )

+20
Mar 04 '15 at 11:51 on
source share

gontard understood correctly .

javac will (optionally) generate its own header file if the class contains its own methods or fields annotated with @Native.

This was a new feature for javac in JDK 8 and has nothing to do with the Jigsaw modular system, as some have suggested. The JDK build system notes that when javac generated new / different native header files and uses this, only recompile native code if necessary.

Jonathan Gibbons, Oracle javac Team

+6
Mar 06 '15 at 4:44
source share

Looking at the problem and fixing it, it looks like it was done to allow the processing of the header file generation for special classes in the puzzle

Jigsaw is a modular system designed for use in the Java SE Platform and JDK. More here

Here is the appropriate set of changes . You can see the comment,

Special processing for generating a header file for classes in a puzzle is a basic module that cannot currently add GenerateNativeHeaders annotations. For these specific classes, the java file and class have the same names, which allows dependencies.

From the sun.nio.ch.IOStatus , I see that for the purpose, in addition to java.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

Therefore, I assume that to solve the puzzle problem, only those that are needed are needed.

+2
02 Mar '15 at 17:45
source share



All Articles