-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use Java 22's foreign function API for Windows #61
base: main
Are you sure you want to change the base?
Conversation
soc
commented
Aug 1, 2024
- Drop all existing mechanisms for retrieving this info on Windows
- This increases the required Java version of the library to 22
try (var arena = Arena.ofConfined()) { | ||
MemorySegment guidSegment = arena.allocate(GUID_LAYOUT); | ||
if (CLSIDFromString(createSegmentFromString(folderId, arena), guidSegment) != 0) { | ||
System.exit(-1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return null
or throw exception instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah - definitely don't want to exit. That was just for my little utility program.
Isn't this a deal breaker? I would imagine many people would like to run this library on Java 21 or Java 17 or even Java 11. |
@sideeffffect I totally agree that this may be a problem for many people at the moment. The hope is that Java 22 will become an acceptable baseline in a few years and people will be able to adopt this version of the library. Until then, they can stay on an older version. |
4333b43
to
b6332c3
Compare
But what about other fixes/improvements which are not related to Windows? For example, Coursier (and/or scala-cli) needs to use a fork of directories-jvm. My hope was the by upstreaming the changes from the fork, the project could eventually come back to the upstream of directories-jvm. @soc would you be open to a PR that sets up sbt-multi-release-jar? |
@sideeffffect I think we could reserve some versions (e. g. v27 - v29) for fixes to the old codebase, and release the one with working Windows support as v30, would that help?
How is the the JVM delivered these days? The JVM version needed for the build tool shouldn't have any impact on the JVM version used for building users' code, right? |
private static String getDir(String folderId) { | ||
try (var arena = Arena.ofConfined()) { | ||
MemorySegment guidSegment = arena.allocate(GUID_LAYOUT); | ||
if (CLSIDFromString(createSegmentFromString(folderId, arena), guidSegment) != 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if it made sense to compute this in Java using java.util.UUID.fromString(x)
.
I'm not sure though how we could convert that UUID
into the struct SHGetKnownFolderPath
needs though ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can see what doing the conversion in java looks like here. https://github.com/maths22/directories-jvm/blob/ffm-poc/src/main/java22/com/maths22/directories/WindowsNativeUtil.java#L54
I'm not going to claim this is the best code for this-it could definitely be cleaned up substantially for readability, but it does function correctly.
I think e.g. Coursier (a project using directories-jvm) needs to be able to run on whatever JVM the user has installed (>= 8), AFAIK.
This would still lock (at least some) downstream dependencies on these "outdated" versions... What downsides do you see in using |
Yikes, they are still doing that? Ok.
That would still require an implementation that didn't require Java 22 for Windows, and I'm not seeing a good option there. |
It doesn't have to be perfect. Better half-broken than none at all. Very sad, but pragmatic approach IMHO. |
I think just staying on v2x of the library should be the thing to do in this case. |
FWIW I have a multi-release jar implementation of approximately the same idea here: https://github.com/maths22/directories-jvm/tree/ffm-poc (though with implementations for the preview versions of all the intermediate java versions as well that had a usable preview) |
Some thoughts:
|
Eventually that will need a solution, but that means for java 22+ you don't actually need any flags at the moment, and java itself logs the necessary warning (so we wouldn't need to do the equivalent ourselves). Java 17 needs both the |
private static String getDir(String folderId) { | ||
try (var arena = Arena.ofConfined()) { | ||
MemorySegment guidSegment = arena.allocate(GUID_LAYOUT); | ||
if (CLSIDFromString(createSegmentFromString(folderId, arena), guidSegment) != 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can see what doing the conversion in java looks like here. https://github.com/maths22/directories-jvm/blob/ffm-poc/src/main/java22/com/maths22/directories/WindowsNativeUtil.java#L54
I'm not going to claim this is the best code for this-it could definitely be cleaned up substantially for readability, but it does function correctly.
throw new AssertionError("failed converting string " + folderId + " to KnownFolderId"); | ||
} | ||
MemorySegment path = arena.allocate(C_POINTER); | ||
SHGetKnownFolderPath(guidSegment, 0, MemorySegment.NULL, path); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Per windows API docs,
The calling process is responsible for freeing this resource once it is no longer needed by calling CoTaskMemFree, whether SHGetKnownFolderPath succeeds or not.
Therefore, as currently implemented there would appear to be a minor memory leak.
(see https://learn.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetknownfolderpath )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can fix this:
Call CoTaskMemFree(path);
after calling SHGetKnownFolderPath
.
Add the following:
private static class CoTaskMemFree {
public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(C_POINTER);
public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(
findOrThrow("CoTaskMemFree"), DESC);
}
/**
* {@snippet lang=c :
* extern void CoTaskMemFree(LPVOID pv)
* }
*/
public static void CoTaskMemFree(MemorySegment pv) {
var handle = CoTaskMemFree.HANDLE;
try {
handle.invokeExact(pv);
} catch (Throwable throwable) {
throw new AssertionError("should not reach here", throwable);
}
}
System.loadLibrary("combase");
may be necessary.
I really wonder what's the "real" solution here, I can't imagine everyone just silencing the warning is the goal the Java devs had in mind... |
JNA seems to work with graalvm nowadays:
but my preferred approach would be to have 2 options in the library, and the dir-dev library knows this by its own: first, and preferred, JNA. and if it is compiled by graalvm or so, FFI. i created a [https://github.com/microsoft/openjdk/issues/628 ticket here with microsofts openjdk], as i failed making a pull request [https://github.com/MovingBlocks/Terasology/pull/5284 using this library in terasology, because of the windows support]. @BenjaminAmos thinks terasology's approach to use JNA is more rubust, and i share that opinion. |
Status:
|
d25f61f
to
91a3c6f
Compare
- Drop all existing mechanisms for retrieving this info on Windows - This increases the required Java version of the library to 22 Fixes #49.