Comments (11)
Want.
from inline-java.
Thinking about this a bit more, it's hard to solve this in full generality. If we had a JVM
monad, and made all code run there instead of IO
, then we could include the current class loader as a parameter inside that monad. We would then change findClass
to bind java.lang.ClassLoader.findClass()
method, rather than the FindClass()
JNI function, passing it the current class loader as an argument. Having a JVM
monad may be a good idea for other reasons (e.g. to fork bound threads by default), but we've shirked away from it so far, because up until now the benefits didn't justify the costs. Such an API change would have a big impact.
One could hope for a short term workaround that doesn't involve such a big impact API change. It'll have to set the class loader globally. Something like adding a new method to jni
called:
setDefaultClassLoader :: J "java.lang.ClassLoader" -> IO ()
from inline-java.
If setDefaultClassLoader
is defined per-thread, then the application has the choice to change it in a particular scope. As in:
withClassLoader :: J "java.lang.ClassLoader" -> IO a -> IO a
withClassLoader c =
bracket (getThreadDefaultClassLoader <* setThreadDefaultClassLoader c)
setThreadDefaultClassLoader
. const
from inline-java.
Hm, good point. We could put the class loader in thread local storage.
from inline-java.
Or can we? How would the default class loader survive a forkIO
?
from inline-java.
hm, elaborate the question?
from inline-java.
In my previous proposal, setDefaultClassLoader
is a global property. Its value is used whenever the JVM cannot tell what class loader to use based on the call stack. Since it's global, it's not thread-local. It would be much better if it could be made thread-local. But then if I set a class loader, then call forkIO
, how do I arrange for the forked thread to use the same class loader as whatever was set in my current thread?
from inline-java.
I thought jni
was intended to be used from bound threads only. Otherwise, in the code:
o <- newObject ...
callObjectMethod o ...
there is no guarantee that callObjectMethod
happens in the same OS thread that owns the local reference to the object created with newObject
.
The call to withClassLoader
in
withClassLoader c (forkOS io)
only affects the current bound thread. The new thread created inside won't use class loader c
unless we change the code to something like
withClassLoader c $ forkOS (withClassLoader c io)
Perhaps it would still be convenient to have a global default class loader, irrespective of whether jni ends up offering a per-thread class loader or not.
from inline-java.
I meant forkOS
yes. Bound or unbound, the problem is avoiding a global variable that is shared by all threads. Sounds like we can't avoid that.
It isn't practical to require that people use a wrapper around forkOS
. Might as well have a JVM
monad in that case.
from inline-java.
I've implemented setDefaultClassLoader
in
master...LeapYear:fd/default-class-loader
and used it in sparkle here:
tweag/sparkle@master...LeapYear:fd/default-class-loader
However, osthreads still fails:
$ git clone [email protected]:LeapYear/sparkle.git; cd sparkle
$ git checkout origin/fd/default-class-loader
$ git submodule update --init --recursive
$ stack --nix build osthreads
$ stack --nix exec -- sparkle package sparkle-example-osthreads
$ stack --nix exec -- spark-submit --master 'local[1]' sparkle-example-osthreads.jar
...
runOS
Exception in thread "Thread-27" java.lang.NoClassDefFoundError: IllegalName: io/tweag/sparkle/function/HaskellFunction2
at java.lang.ClassLoader.preDefineClass(ClassLoader.java:654)
at java.lang.ClassLoader.defineClass(ClassLoader.java:761)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
Exception in thread "Thread-27" java.lang.NoClassDefFoundError: io/tweag/sparkle/function/HaskellFunction2
Caused by: java.lang.ClassNotFoundException: io.tweag.sparkle.function.HaskellFunction2
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
sparkle-worker: JavaException (J 0x00002aab600029b8)
from inline-java.
Please, reopen if there is anything we can do here. Currently the user needs to be concerned with the default class loader that JNI uses, and the context class loader that the current thread has set.
from inline-java.
Related Issues (20)
- Optimize disposal of IOVectors
- Bound the queue of the finalizer thread
- loadJavaWrappers leaks one local reference per class to load
- Move the RWLock implementation in jni to use stm
- Prepare jvm-batching.jar to be released in maven central HOT 3
- Handle modified UTF-8 correctly HOT 1
- Don't write on stderr each time an Exception occurs HOT 2
- ghc: could not execute: ./cpphs-cpp HOT 3
- Create targets in bazel to build and run benchmarks
- Have tests in jvm-batching and jvm-streaming running in bazel
- Set the CLASSPATH in a wrapper for binaries HOT 1
- Handle uncaught JVMExceptions in withJVM
- The bazel build breaks at fetch of repository in WSL HOT 4
- Existing Project Integration HOT 4
- Migrate CI to github workflows HOT 3
- cpp:hello-success-test fails on macOS Monterey (aarch64) HOT 4
- Multiple withJVM calls hangs HOT 4
- Updates for text 2.x package HOT 5
- haskell.nix support for `jni` and `jvm` packages HOT 4
- don't rely on `JNI_GetCreatedJavaVMs` HOT 11
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from inline-java.