-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
Get JNIEnv pointer #812
Get JNIEnv pointer #812
Conversation
@ncruces if I read the referenced issue correctly, you are not interested in the JNIEnv Pointer on the java side, but on the native side. I see an alternative:
public final class CurrentJNIEnv {
public static CurrentJNIEnv INSTANCE = new CurrentJNIEnv();
}
This way the Java->Native transition needs to be done only once and you are sure to access the "correct" JNI env. As a general comment, if the native interface is changed, the changes done to the lib/native directory need to be commited with the change, as the build skript takes care of invalidating the native libraries, that don't work anymore. @twall Timothy could you please also have a look at this? |
Yes, that's a possibility. It'd be cleaner for client code. But it's a bigger change and makes everyone else pay a (small) price on every dispatch for something I imagine isn't that common. Right now I'm caching the environment pointer on my end as a thread local static, so I only pay the price once per thread. Then, it's a non issue for me. But I can sketch that alternative and do a separate PR for you to decide which is better? I'd need to change direct dispatch as well. |
Sorry for that. About binaries, I can do those, but I don't think I can for every applicable platform? I've done Linux x86-64 and all the Androids. |
With regard for the binaries: I can do the currently supported linux variants and windows. I have a way to build the darwin binary and solaris x64. Timothy should be able to do the AIX build. Long story short: building the binaries is a doable job. My fear with your current approach is users using the wrong JNIEnv pointer and not taking the same care as you. Having the environment provide the "correct" JNIEnv removes that option to shoot onself into the foot. |
OK. We agree on that one. Most non-hackish uses of JNIEnv should be calling a native function that expects it (along with some jobjects). For the more hackish uses there's always my gist. I'll have a go at it then. Do you want me to base this work on the current branch, or on 5.0.0? |
OK, so this was easier than I thought: 0c3bc06 It passes the tests, and works for me. Any feedback is appreciated. I imagine I've also run into some probable bugs (and improvements) when going through the source code. I'll create separate issues/branches for each of those. |
Handling of JNIEnv was one of the original use cases for the "allow objects" flag. This looks like a good implementation for ensuring the proper env is used. Good thinking, @matthiasblaesing Thanks for the contributions, @ncruces |
@ncruces I did some more reading through the code and while going through the changes for supporting direct mapping of objects I noticed, that the unittest is not a real test (https://github.com/ncruces/jna/commit/86c21b8e971bbc8b3b744837bd0fad9ee30fd6f4). Your implementation of diff --git a/test/com/sun/jna/DirectReturnTypesTest.java b/test/com/sun/jna/DirectReturnTypesTest.java
index afe0778..696f7a0 100644
--- a/test/com/sun/jna/DirectReturnTypesTest.java
+++ b/test/com/sun/jna/DirectReturnTypesTest.java
@@ -23,7 +23,6 @@
*/
package com.sun.jna;
-import java.util.Map;
import java.util.Collections;
/** Exercise a range of native methods.
@@ -94,6 +93,7 @@ public class DirectReturnTypesTest extends ReturnTypesTest {
@Override
protected void setUp() {
lib = new DirectTestLibrary();
+ libSupportingObject = new DirectObjectTestLibrary();
}
public static class DirectObjectTestLibrary extends DirectTestLibrary {
@@ -123,12 +123,6 @@ public class DirectReturnTypesTest extends ReturnTypesTest {
return new DirectNativeMappedLibrary();
}
-
- @Override
- public void testReturnObject() {
- lib = new DirectObjectTestLibrary();
- }
-
// Override not-yet-supported tests
@Override
public void testReturnPointerArray() { }
diff --git a/test/com/sun/jna/ReturnTypesTest.java b/test/com/sun/jna/ReturnTypesTest.java
index 4a60ed8..2727181 100644
--- a/test/com/sun/jna/ReturnTypesTest.java
+++ b/test/com/sun/jna/ReturnTypesTest.java
@@ -129,26 +129,28 @@ public class ReturnTypesTest extends TestCase {
}
TestLibrary lib;
+ TestLibrary libSupportingObject;
@Override
protected void setUp() {
lib = Native.loadLibrary("testlib", TestLibrary.class);
+ libSupportingObject = Native.loadLibrary("testlib", TestLibrary.class, Collections.singletonMap(Library.OPTION_ALLOW_OBJECTS, Boolean.TRUE));
}
@Override
protected void tearDown() {
lib = null;
+ libSupportingObject = null;
}
public void testReturnObject() throws Exception {
- lib = Native.loadLibrary("testlib", TestLibrary.class, Collections.singletonMap(Library.OPTION_ALLOW_OBJECTS, Boolean.TRUE));
- assertNull("null value not returned", lib.returnObjectArgument(null));
+ assertNull("null value not returned", libSupportingObject.returnObjectArgument(null));
final Object VALUE = new Object() {
@Override
public String toString() {
return getName();
}
};
- assertEquals("Wrong object returned", VALUE, lib.returnObjectArgument(VALUE));
+ assertEquals("Wrong object returned", VALUE, libSupportingObject.returnObjectArgument(VALUE));
}
public void testReturnObjectUnsupported() throws Exception {
One nice thing would be an explanation why native code does not need changing for direct passing of Java objects (CVT_OBJECT is not used on native side). I think I got it, but would be interested in your reasoning. The changes for passing JNIEnv in 0c3bc06 look good to me. I suggest this:
|
One thing I forgot: If no api breaks are planned, I would base the changes on master. I created the jna-5.0.0 branch for changes that affect the API or backwards compatibility. My plan is: Merge the changes done to master into the JNA 5.0.0 branch, so that this does not stop development. |
You are of course right about the test, I messed up. I've worked on that according to your suggestion, but changed it for the Regarding Regarding binaries, I'm not seeing |
Not wanting to overwhelm you with low priority stuff, going down the
|
@ncruces could you please have a look at this branch: https://github.com/matthiasblaesing/jna/tree/ncruces-get-env This is a partitial merge of your work. The changes I added:
If this is ok with you I'd merge the into master. With regard to the new PR I would hold back on rebuilding the native parts until that is merged. If your wondering about the automatic invalidation of the native libraries. For that to work the correct sequence is (this is only an information and no request for changes!):
After step 2 all binaries in |
That's fine by me. For now, I'm be using custom built binaries (so no pressure on you guys), but I'll gladly go back to Maven when this lands! Regarding the invalidation of the native libraries: if I understand you correctly this means the invalidation only happens when the checksum changes (which is a proxy for a change in the native API). Correct? The thing is: the solution we came too does not change the native API. Features were added, and the native part needs to be rebuilt for tests to pass, but the API doesn't change. Maybe |
@ncruces You are right, the minor version needs to be bumped, as the changes you did, did not affect the JNI checksum, the automatic did not catch that - sorry about the confusion. |
Suggested fix for #805. Implemented on top of #811 (related).
Changes the native side (updates version and hash). Includes a test case.
Hope its up to standard.