我理解@Native注释的使用.
指示可以从本机代码引用定义常量值的字段.注释可以用作生成本机头文件的工具的提示,以确定是否需要头文件,如果需要,它应该包含哪些声明.
然而,在阅读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
Run Code Online (Sandbox Code Playgroud)
编辑:我刚刚注意到,这也适用于MAX_VALUE和MIN_VALUE同一类的.
编辑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
Run Code Online (Sandbox Code Playgroud)
为什么SIZE仅为整数和长整数@Native?
gon*_*ard 21
TLDR:跳到结论
为什么SIZE仅为整数和长整数@Native?
@Native我在邮件列表上搜索了一些内容.我找到了一些有趣的东西.
首先
,引入了注释(1 2)javax.tools.annotation.ForceNativeHeader
在类上触发javah.
它用于com.sun.tools.javac.processing.NativeapiVisitor.通过查看代码,我们可以看到,如果类声明了一些本机方法或者类被注释,则会生成本机头@ForceNativeHeader.
后来这个注释被重命名为GenerateNativeHeader(1 2).
然后将 这个注释添加到几种类型(特别是整数和长整数)中,并带有一个有趣的注释:
/* No native methods here, but the constants are needed in the supporting JNI code */
@GenerateNativeHeader
public final class Long extends Number implements Comparable<Long> {...
Run Code Online (Sandbox Code Playgroud)
但是通过添加此注释,它会从基本模块向包含javax.tools的模块添加一个有问题的依赖项.所以注释从取出Integer,并Long和这些文件都明确地加入到构建过程中,因为没有更多的自动生成的头......一"(希望是暂时的)黑客".
因此,在Integer和Long中java.lang.annotation.Native 创建并使用了新的注释.注释设置为a .TargetType FIELD
注释应该直接应用于需要导出的常量字段 - 而不是整个类.
这个东西的所有目的是:
javac可以为包含本机方法的类生成本机头.
它的情况Integer和Long
这是JEP 139的一部分:增强javac以提高构建速度:
javah将自动在包含本机方法的任何类上运行,生成的C-header将放在(-h)headerdir中.新注释@ForceNativeHeader用于具有需要导出到JNI的最终静态基元但没有本机方法的类.
我在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
...
Run Code Online (Sandbox Code Playgroud)
然后我试图@Native从Integer字段中删除,我试图再次建立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.
Run Code Online (Sandbox Code Playgroud)
逻辑上,因为尚未生成标头.
我还确认它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
Run Code Online (Sandbox Code Playgroud)
喜欢 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
Run Code Online (Sandbox Code Playgroud)
喜欢 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
Run Code Online (Sandbox Code Playgroud)
并喜欢 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
Run Code Online (Sandbox Code Playgroud)
但都没有 Short
find . \( -name "*.c" -o -name "*.cpp" \) -exec grep "java_lang_Short.h" {} \; -print
Run Code Online (Sandbox Code Playgroud)
也不Byte是Character.
在所有这些类型的,只是 Integer,Long,Float,Double都在使用的jdk的本地源代码.
并且只有Integer和Long字段被注释,@Native因为它们没有本机方法(而不是Float和Double)
如果类包含使用@Native注释的本机方法或字段,javac将(可选)生成本机头文件.
这是JDK 8中javac的一个新功能,与Jigsaw模块系统无关,正如一些人猜想的那样.JDK构建系统在javac生成新的/不同的本机头文件时注意到,并且在必要时使用它仅触发本机代码的重新编译.
Oracle的javac团队Jonathan Gibbons
| 归档时间: |
|
| 查看次数: |
1764 次 |
| 最近记录: |