Странное поведение Java MethodHandle.invokeExactJAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Странное поведение Java MethodHandle.invokeExact

Сообщение Anonymous »

Вот минимальный рабочий пример (требуется Java 22 или новее):
(просто использование libc free для уточнения поведения)

Код: Выделить всё

import java.lang.foreign.*;
import java.lang.invoke.MethodHandle;

public class Main {
public static final Linker nativeLinker = Linker.nativeLinker();
public static final SymbolLookup stdlibLookup = nativeLinker.defaultLookup();
public static final SymbolLookup loaderLookup = SymbolLookup.loaderLookup();

private static final FunctionDescriptor DESCRIPTOR$free = FunctionDescriptor.ofVoid(ValueLayout.ADDRESS);
private static final MethodHandle HANDLE$free =
loaderLookup.find("free")
.or(() -> stdlibLookup.find("free"))
.map(symbolSegment -> nativeLinker.downcallHandle(symbolSegment, DESCRIPTOR$free))
.orElseThrow(() -> new RuntimeException("libc function free not found but y?"));

public static void free(MemorySegment address) {
try {
// I want to allow user code to use Java null and MemorySegment.NULL (C NULL) interchangeably
HANDLE$free.invokeExact(address != null ? address : MemorySegment.NULL);
} catch (Throwable throwable) {
throwable.printStackTrace(System.err);
}
}

public static void main(String[] args) {
free(null); // free(MemorySegment.NULL) will produce same result
}
}
Запустите программу, и возникнет исключение:

Код: Выделить всё

java.lang.invoke.WrongMethodTypeException: handle's method type (MemorySegment)void but found (Object)void
at java.base/java.lang.invoke.Invokers.newWrongMethodTypeException(Invokers.java:521)
at java.base/java.lang.invoke.Invokers.checkExactType(Invokers.java:530)
at Main.free(Main.java:19)
at Main.main(Main.java:26)
Java жалуется, что аргумент, используемый для вызова IssueExact, является объектом, а не MemorySegment. Однако выражение

Код: Выделить всё

address != null ? address : MemorySegment.NULL
конечно, должен иметь тип MemorySegment. А если внести небольшую модификацию в код:

Код: Выделить всё

    public static void free(MemorySegment address) {
try {
MemorySegment temp = address != null ? address : MemorySegment.NULL;
HANDLE$free.invokeExact(temp);
} catch (Throwable throwable) {
throwable.printStackTrace(System.err);
}
}
работает правильно.
А еще
  • Код: Выделить всё

    HANDLE$free.invoke(address != null ? address : MemorySegment.NULL)
    работает
  • Код: Выделить всё

    HANDLE$free.invokeExact((MemorySegment)(address != null ? address : MemorySegment.NULL))
    работает, но
  • Код: Выделить всё

    HANDLE$free.invokeExact((address != null ? address : MemorySegment.NULL))
    не работает
Это какой-то преднамеренный замысел, ограничение реализации или ошибки JVM?

Подробнее здесь: https://stackoverflow.com/questions/790 ... nvokeexact
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

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

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»