Подтвердить что ты не робот

Почему константа SIZE только @Native для Integer и Long?

Я понимаю использование аннотации @Native.

Указывает, что поле, определяющее постоянное значение, может ссылаться от нативного кода. Аннотацию можно использовать в качестве подсказки инструментами, которые генерировать собственные файлы заголовков, чтобы определить, является ли файл заголовка требуется, и если да, то какие декларации он должен содержать.

Однако, читая исходный код java, я заметил, что в классе 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

Изменить: Я только заметил, что это также относится к 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

Почему константа SIZE только @Native для целых и длинных?

4b9b3361

Ответ 1

TL;DR: переход к заключению


Почему константа SIZE только @Native для целых и длинных?

Краткая история @Native

Я сделал несколько поисков в списках рассылки. Я нашел интересные вещи.

Сначала аннотация (1 2) javax.tools.annotation.ForceNativeHeader  был введен в

чтобы вызвать javah для класса.

Используется com.sun.tools.javac.processing.NativeapiVisitor. Посмотрев на код, мы видим, что собственный заголовок генерируется, если класс объявляет некоторые собственные методы или класс аннотируется @ForceNativeHeader.

Позже эта аннотация была переименована в GenerateNativeHeader (1 2).

Затем эта аннотация добавлена ​​к нескольким типам (особенно Integer и 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> {...

Но добавив эту аннотацию, добавьте проблемную зависимость от базового модуля к модулю, содержащему javax.tools. Таким образом, аннотация была удалена из Integer и Long, и эти файлы были явно добавлен в процесс сборки, поскольку заголовок больше не генерируется автоматически... a "(надеюсь, временный) взлом" .

Итак была создана новая аннотация java.lang.annotation.Native и использована в Integer и Long. Аннотации были установлены как TargetType FIELD.

аннотация должна быть непосредственно применена к постоянным полям, которые необходимо экспортировать, а не к классу в целом.


Вся эта цель состоит в следующем:

javac может генерировать собственные заголовки для классов, содержащих собственные методы.

Это случай Integer и Long

это было частью JEP 139: Enhance javac для улучшения скорости сборки:

javah будет автоматически запускаться в любом классе, который содержит собственные методы, и сгенерированные C-заголовки будут помещены в (-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
    ...

Затем я попытался удалить @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.

логически, поскольку заголовок не был сгенерирован.

Я также подтвердил, что 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

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

и как 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)

Ответ 2

gontard правильно понял.

javac будет (необязательно) генерировать собственный заголовочный файл, если класс содержит собственные методы или поля, аннотированные с @Native.

Это была новая функция для javac в JDK 8 и не имеет ничего общего с модульной системой Jigsaw, как некоторые предположили. Система сборки JDK отмечает, что когда javac генерировал новые/разные собственные файлы заголовков и использует это, только при необходимости перекомпилировать собственный код.

Джонатан Гиббонс, Команда Oracle javac

Ответ 3

Рассматривая проблему и исправляя ее, похоже, что это было сделано для разрешения обработки генерации файла заголовка для специальных классов в головоломке

Jigsaw - это модульная система, предназначенная для использования в Java SE Platform и JDK. Подробнее здесь

Вот соответствующий набор изменений. Вы можете увидеть комментарий,

Специальная обработка генерации файла заголовка для классов в головоломке базовый модуль, который в настоящее время не может добавить аннотации GenerateNativeHeaders. Для этих конкретных классов java файл и класс имеет те же имена, что позволяет зависимостей.

Из набора изменений я вижу, что для цели в дополнение к java.lang.Integer и java.lang.Long также некоторые свойства в java.net.SocketOptions, sun.nio.ch.IOStatus, java.io.FileSystem были изменены на @Native.

Поэтому я предполагаю, что для решения проблемы с головоломкой нужны только те, которые необходимы.