为什么 SIZE 常量只有 @Native 用于 Integer 和 Long?
Why is the SIZE constant only @Native for Integer and Long?
我了解 @Native
注释的用法。
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.
但是,在阅读 java 源代码时,我注意到在 class Integer
和 Long
中 SIZE
常量是 @Native
而它不适用于 Float、Byte、Double、Short 和 Character。
请注意,SIZE 常量表示用于表示实际值的位数。
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
编辑: 我刚刚注意到这也适用于相同 classes 的 MAX_VALUE
和 MIN_VALUE
。
编辑 2 : 我有空闲时间对此做了一些研究,并查看了 Long、Float 等的 header 文件。 classes 我曾希望弄清楚常量不存在于其他 headers 中,但不幸的是它们存在。
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
为什么 Integer 和 Long 的 SIZE 常量只有@Native?
查看问题和修复,似乎已完成此操作以解决 jigsaw
中特殊 类 的头文件生成处理问题
Jigsaw 是指定用于 Java SE 平台和 JDK 的模块系统。更多详情 here
这里是对应的changeset。可以看到评论,
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.
从变更集中,我看到除了 java.lang.Integer
和 java.lang.Long
之外,还有 java.net.SocketOptions
、sun.nio.ch.IOStatus
、[=14 中的一些属性=] 已更改为 @Native
。
所以我假设只需要那些来解决拼图的依赖关系。
TLDR:跳到结论
Why is the SIZE constant only @Native for Integer and Long?
@Native
的简史
我在邮件列表中进行了一些搜索。我发现了一些有趣的东西。
首先一个注解(1 2) javax.tools.annotation.ForceNativeHeader
被介绍给
to trigger javah on a class.
被com.sun.tools.javac.processing.NativeapiVisitor
使用。通过查看代码可以看出,如果class声明了一些native方法或者class注解了@ForceNativeHeader
.
,那么就会生成native header
后来此注释被重命名为GenerateNativeHeader
(1 2)。
Then this annotation was added to several types (especially Integer and Long) 加上有趣的评论:
/* No native methods here, but the constants are needed in the supporting JNI code */
@GenerateNativeHeader
public final class Long extends Number implements Comparable<Long> {...
但是 通过添加这个注释它添加了 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".
所以一个新注释java.lang.annotation.Native
was created and used in Integer and Long。注释设置为 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.
这些东西的全部目的是:
javac could generate native headers for classes containing native methods.
是Integer
和Long
的情况
这是 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.
基本实验
我在 JDK 上做了一个基本的实验。我克隆了 open-jdk 林并成功构建了它。正如预期的那样,为 Integer
和 Long
(感谢 @Native
)以及为 Float
和 Double
(感谢他们的原生方法)但不适用于 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
...
然后我尝试从 Integer
字段中删除 @Native
并尝试重新构建 jdk
但出现错误:
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.
合乎逻辑,因为 header 尚未生成。
我还确认 java_lang_Integer.h
包含在 几个 c 和 cpp 文件中:
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
喜欢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
喜欢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
喜欢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
但Short
find . \( -name "*.c" -o -name "*.cpp" \) -exec grep "java_lang_Short.h" {} \; -print
也不Byte
,也不Character
。
结论
在所有这些类型中,只有 Integer
、Long
、Float
、Double
用于jdk.
的本机源代码
并且只有 Integer
和 Long
字段用 @Native
注释,因为它们 没有本地方法(相对于 Float
和 Double
)
.
如果 class 包含用 @Native 注释的本机方法或字段,javac 将(可选)生成本机头文件。
这是 JDK 8 中 javac 的新功能,与某些人猜测的 Jigsaw 模块系统无关。 JDK 构建系统会记录 javac 何时生成 new/different 本机头文件,并使用它仅在必要时触发本机代码的重新编译。
乔纳森·吉本斯,
Oracle 的 javac 团队
我了解 @Native
注释的用法。
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.
但是,在阅读 java 源代码时,我注意到在 class Integer
和 Long
中 SIZE
常量是 @Native
而它不适用于 Float、Byte、Double、Short 和 Character。
请注意,SIZE 常量表示用于表示实际值的位数。
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
编辑: 我刚刚注意到这也适用于相同 classes 的 MAX_VALUE
和 MIN_VALUE
。
编辑 2 : 我有空闲时间对此做了一些研究,并查看了 Long、Float 等的 header 文件。 classes 我曾希望弄清楚常量不存在于其他 headers 中,但不幸的是它们存在。
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
为什么 Integer 和 Long 的 SIZE 常量只有@Native?
查看问题和修复,似乎已完成此操作以解决 jigsaw
中特殊 类 的头文件生成处理问题Jigsaw 是指定用于 Java SE 平台和 JDK 的模块系统。更多详情 here
这里是对应的changeset。可以看到评论,
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.
从变更集中,我看到除了 java.lang.Integer
和 java.lang.Long
之外,还有 java.net.SocketOptions
、sun.nio.ch.IOStatus
、[=14 中的一些属性=] 已更改为 @Native
。
所以我假设只需要那些来解决拼图的依赖关系。
TLDR:跳到结论
Why is the SIZE constant only @Native for Integer and Long?
@Native
的简史
我在邮件列表中进行了一些搜索。我发现了一些有趣的东西。
首先一个注解(1 2) javax.tools.annotation.ForceNativeHeader
被介绍给
to trigger javah on a class.
被com.sun.tools.javac.processing.NativeapiVisitor
使用。通过查看代码可以看出,如果class声明了一些native方法或者class注解了@ForceNativeHeader
.
后来此注释被重命名为GenerateNativeHeader
(1 2)。
Then this annotation was added to several types (especially Integer and Long) 加上有趣的评论:
/* No native methods here, but the constants are needed in the supporting JNI code */
@GenerateNativeHeader
public final class Long extends Number implements Comparable<Long> {...
但是 通过添加这个注释它添加了 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".
所以一个新注释java.lang.annotation.Native
was created and used in Integer and Long。注释设置为 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.
这些东西的全部目的是:
javac could generate native headers for classes containing native methods.
是Integer
和Long
这是 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.
基本实验
我在 JDK 上做了一个基本的实验。我克隆了 open-jdk 林并成功构建了它。正如预期的那样,为 Integer
和 Long
(感谢 @Native
)以及为 Float
和 Double
(感谢他们的原生方法)但不适用于 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
...
然后我尝试从 Integer
字段中删除 @Native
并尝试重新构建 jdk
但出现错误:
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.
合乎逻辑,因为 header 尚未生成。
我还确认 java_lang_Integer.h
包含在 几个 c 和 cpp 文件中:
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
喜欢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
喜欢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
喜欢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
但Short
find . \( -name "*.c" -o -name "*.cpp" \) -exec grep "java_lang_Short.h" {} \; -print
也不Byte
,也不Character
。
结论
在所有这些类型中,只有 Integer
、Long
、Float
、Double
用于jdk.
并且只有 Integer
和 Long
字段用 @Native
注释,因为它们 没有本地方法(相对于 Float
和 Double
)
如果 class 包含用 @Native 注释的本机方法或字段,javac 将(可选)生成本机头文件。
这是 JDK 8 中 javac 的新功能,与某些人猜测的 Jigsaw 模块系统无关。 JDK 构建系统会记录 javac 何时生成 new/different 本机头文件,并使用它仅在必要时触发本机代码的重新编译。
乔纳森·吉本斯, Oracle 的 javac 团队