Code Monkey home page Code Monkey logo

Comments (11)

robinbb avatar robinbb commented on May 30, 2024

Want.

from inline-java.

mboes avatar mboes commented on May 30, 2024

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.

facundominguez avatar facundominguez commented on May 30, 2024

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.

mboes avatar mboes commented on May 30, 2024

Hm, good point. We could put the class loader in thread local storage.

from inline-java.

mboes avatar mboes commented on May 30, 2024

Or can we? How would the default class loader survive a forkIO?

from inline-java.

facundominguez avatar facundominguez commented on May 30, 2024

hm, elaborate the question?

from inline-java.

mboes avatar mboes commented on May 30, 2024

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.

facundominguez avatar facundominguez commented on May 30, 2024

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.

mboes avatar mboes commented on May 30, 2024

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.

facundominguez avatar facundominguez commented on May 30, 2024

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.

facundominguez avatar facundominguez commented on May 30, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.