/
githubmirror
/
galahad
Обзор
Документация
Войти
/
githubmirror
/
galahad
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/java.base/share/classes/jdk/internal/foreign/SystemLookup.java
219 строк
7 KB
Jiangli Zhou
8355080: java.base/jdk.internal.foreign.SystemLookup.find() doesn't work on static JDK
28 апр 2025, 21:55
28 апр 2025, 21:55
acd93df
Код
Авторство
О чём код?
/* * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package jdk.internal.foreign; import jdk.internal.loader.NativeLibraries; import jdk.internal.loader.NativeLibrary; import jdk.internal.loader.RawNativeLibraries; import jdk.internal.util.OperatingSystem; import jdk.internal.util.StaticProperty; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; import java.lang.foreign.SequenceLayout; import java.lang.foreign.SymbolLookup; import java.lang.invoke.MethodHandles; import java.nio.file.Files; import java.nio.file.Path; import java.util.Objects; import java.util.Optional; import java.util.function.Function; import static java.lang.foreign.ValueLayout.ADDRESS; public final class SystemLookup implements SymbolLookup { private SystemLookup() { } private static final SystemLookup INSTANCE = new SystemLookup(); /* A fallback lookup, used when creation of system lookup fails. */ private static final SymbolLookup FALLBACK_LOOKUP = name -> { Objects.requireNonNull(name); return Optional.empty(); }; /* * On POSIX systems, dlsym will allow us to lookup symbol in library dependencies; the same trick doesn't work * on Windows. For this reason, on Windows we do not generate any side-library, and load msvcrt.dll directly instead. */ private static final SymbolLookup SYSTEM_LOOKUP = makeSystemLookup(); private static SymbolLookup makeSystemLookup() { try { if (OperatingSystem.isWindows()) { return makeWindowsLookup(); } else { return sysLookup(); } } catch (Throwable ex) { // This can happen in the event of a library loading failure - e.g. if one of the libraries the // system lookup depends on cannot be loaded for some reason. In such extreme cases, rather than // fail, return a dummy lookup. return FALLBACK_LOOKUP; } } private static SymbolLookup makeWindowsLookup() { String systemRoot = System.getenv("SystemRoot"); Path system32 = Path.of(systemRoot, "System32"); Path ucrtbase = system32.resolve("ucrtbase.dll"); Path msvcrt = system32.resolve("msvcrt.dll"); boolean useUCRT = Files.exists(ucrtbase); Path stdLib = useUCRT ? ucrtbase : msvcrt; SymbolLookup lookup = stdLibLookup(libs -> libs.load(stdLib)); if (useUCRT) { // use a fallback lookup to look up inline functions from fallback lib SymbolLookup fallbackLibLookup = sysLookup(); @SuppressWarnings("restricted") MemorySegment funcs = fallbackLibLookup.findOrThrow("funcs") .reinterpret(WindowsFallbackSymbols.LAYOUT.byteSize()); Function<String, Optional<MemorySegment>> fallbackLookup = name -> Optional.ofNullable(WindowsFallbackSymbols.valueOfOrNull(name)) .map(symbol -> funcs.getAtIndex(ADDRESS, symbol.ordinal())); final SymbolLookup finalLookup = lookup; lookup = name -> { Objects.requireNonNull(name); if (Utils.containsNullChars(name)) return Optional.empty(); return finalLookup.find(name).or(() -> fallbackLookup.apply(name)); }; } return lookup; } private static SymbolLookup lookup(NativeLibrary lib) { return name -> { Objects.requireNonNull(name); if (Utils.containsNullChars(name)) return Optional.empty(); try { long addr = lib.lookup(name); return addr == 0 ? Optional.empty() : Optional.of(MemorySegment.ofAddress(addr)); } catch (NoSuchMethodException e) { return Optional.empty(); } }; } private static SymbolLookup stdLibLookup(Function<RawNativeLibraries, NativeLibrary> loader) { NativeLibrary lib = loader.apply(RawNativeLibraries.newInstance(MethodHandles.lookup())); return lookup(lib); } @SuppressWarnings("restricted") private static SymbolLookup sysLookup() { NativeLibraries libs = NativeLibraries.newInstance(null); NativeLibrary lib = libs.loadLibrary(SymbolLookup.class, "syslookup"); return lookup(lib); } public static SystemLookup getInstance() { return INSTANCE; } @Override public Optional<MemorySegment> find(String name) { return SYSTEM_LOOKUP.find(name); } // fallback symbols missing from ucrtbase.dll // this list has to be kept in sync with the table in the companion native library private enum WindowsFallbackSymbols { // stdio fprintf, fprintf_s, fscanf, fscanf_s, fwprintf, fwprintf_s, fwscanf, fwscanf_s, printf, printf_s, scanf, scanf_s, snprintf, sprintf, sprintf_s, sscanf, sscanf_s, swprintf, swprintf_s, swscanf, swscanf_s, vfprintf, vfprintf_s, vfscanf, vfscanf_s, vfwprintf, vfwprintf_s, vfwscanf, vfwscanf_s, vprintf, vprintf_s, vscanf, vscanf_s, vsnprintf, vsnprintf_s, vsprintf, vsprintf_s, vsscanf, vsscanf_s, vswprintf, vswprintf_s, vswscanf, vswscanf_s, vwprintf, vwprintf_s, vwscanf, vwscanf_s, wprintf, wprintf_s, wscanf, wscanf_s, // time gmtime; static WindowsFallbackSymbols valueOfOrNull(String name) { try { return valueOf(name); } catch (IllegalArgumentException e) { return null; } } static final SequenceLayout LAYOUT = MemoryLayout.sequenceLayout( values().length, ADDRESS); } }