Java 为什么整数和Long的大小常量仅为@Native?

Java 为什么整数和Long的大小常量仅为@Native?,java,java-8,Java,Java 8,我理解注释的用法 指示可以引用定义常量值的字段 来自本机代码。注释可用作以下工具的提示: 生成本机头文件以确定头文件是否为 必需的,如果需要,应该包含哪些声明 然而,在阅读java源代码时,我注意到在类Integer和Long中,SIZE常量是@Native,而不是浮点、字节、双精度、短字符和字符 请注意,SIZE常量表示用于表示实际值的位数 public static final int SIZE = 8;//Byte public static final int SIZE = 16;//C

我理解注释的用法

指示可以引用定义常量值的字段 来自本机代码。注释可用作以下工具的提示: 生成本机头文件以确定头文件是否为 必需的,如果需要,应该包含哪些声明

然而,在阅读java源代码时,我注意到在类
Integer
Long
中,
SIZE
常量是
@Native
,而不是浮点、字节、双精度、短字符和字符

请注意,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

编辑:我刚刚注意到,这也适用于相同类别的
MAX\u值
MIN\u值


编辑2:我有空闲时间对此做一些研究,查看Long、Float等类的头文件,我希望找出其他头文件中不存在常量,但不幸的是它们存在

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


为什么整型和长型的大小常量仅为@Native?

查看问题和解决方案,看起来这样做是为了解决jigsaw中特殊类的头文件生成处理问题

Jigsaw是一个指定用于JavaSE平台和JDK的模块系统。更多细节

下面是一个对应的例子。你可以看到一条评论

jigsaw中类头文件生成的特殊处理 当前无法添加注释的基本模块 发电领导者。对于这些特定类,java文件和 该类具有相同的名称,可以对 依赖关系

从变更集中,我看到除了
java.lang.Integer
java.lang.Long
之外,
java.net.SocketOptions
sun.nio.ch.IOStatus
java.io.FileSystem
中的一些属性也被更改为
@Native


因此,我假设只需要这些就可以用jigsaw解决依赖关系。

TLDR:跳到结论


为什么整数和Long的大小常量仅为@Native

@Native
我在邮件列表上搜索了一下。我发现了一些有趣的东西

首先注释() 被介绍给

在类上触发javah

它由用户使用。通过查看代码,我们可以看到,如果类声明了一些本机方法,或者如果类被注释为
@ForceNativeHeader
,则会生成本机头

之后此注释被重命名为()

然后(尤其是和)加上一句相互质问的评论:

/* No native methods here, but the constants are needed in the supporting JNI code */
@GenerateNativeHeader
public final class Long extends Number implements Comparable<Long> {...
然后,我尝试从
整数
字段中删除
@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.
逻辑上,因为尚未生成标头

我还确认,
java\u lang\u 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
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
像是双倍的

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
也不是
字节
,也不是
字符


结论 在所有这些类型中,jdk的本机源代码中仅使用了整数、
浮点

只有
整数
字段用
@Native
注释,因为它们没有本机方法(与
浮点
双精度
相反)

<

如果类包含用@native注释的本机方法或字段,javac将(可选)生成本机头文件

这是JDK 8中javac的一个新特性,与Jigsaw模块系统无关,正如一些人猜测的那样。JDK构建系统会记录javac何时生成了新的/不同的本机头文件,并仅在必要时使用该头文件触发本机代码的重新编译

乔纳森·吉本斯,
Oracle的javac团队

删除了特殊处理,并将其替换为
@Native
。这并不能解释为什么只注释Integer和Long(而不是其他基本包装器)(注意特殊处理也排除了其他包装器)。不过,检查
hg
还是个好主意。我假设jigsaw只需要这些类,这就是为什么其他类没有被触及的原因。这并不能解释为什么只有Long和Integer的大小是本机的,这只是证实了我所看到的。我也不认为,因为这是在拼图上完成的,所以这是专门为拼图做的。回答“它是在JDK上完成的,以解决依赖性问题”是解释为什么它是在Jigsaw中完成的一个好答案吗?特殊处理和将@Native移动到java.lang.annotation是针对Jigsaw的,但我打赌这些字段的使用(自动生成或不自动生成)你的意思是说,由于JDK模块化项目,Java需要使本地JVM实现的
Long
Integer
表示大小以位为单位可见吗?我很难相信这就是为什么。。。
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
find .  \( -name "*.c" -o -name "*.cpp" \) -exec grep "java_lang_Short.h" {} \; -print