Available Coroutine Libraries in Java
Asked Answered
C

9

50

I would like to do some stuff in Java that would be clearer if written using concurrent routines, but for which full-on threads are serious overkill. The answer, of course, is the use of coroutines, but there doesn't appear to be any coroutine support in the standard Java libraries and a quick Google on it brings up tantalising hints here or there, but nothing substantial.

Here's what I've found so far:

  • JSIM has a coroutine class, but it looks pretty heavyweight and conflates, seemingly, with threads at points. The point of this is to reduce the complexity of full-on threading, not to add to it. Further I'm not sure that the class can be extracted from the library and used independently.
  • Xalan has a coroutine set class that does coroutine-like stuff, but again it's dubious if this can be meaningfully extracted from the overall library. It also looks like it's implemented as a tightly-controlled form of thread pool, not as actual coroutines.
  • There's a Google Code project which looks like what I'm after, but if anything it looks more heavyweight than using threads would be. I'm basically nervous of something that requires software to dynamically change the JVM bytecode at runtime to do its work. This looks like overkill and like something that will cause more problems than coroutines would solve. Further it looks like it doesn't implement the whole coroutine concept. By my glance-over it gives a yield feature that just returns to the invoker. Proper coroutines allow yields to transfer control to any known coroutine directly. Basically this library, heavyweight and scary as it is, only gives you support for iterators, not fully-general coroutines.
  • The promisingly-named Coroutine for Java fails because it's a platform-specific (obviously using JNI) solution.

And that's about all I've found.

I know about the native JVM support for coroutines in the Da Vinci Machine and I also know about the JNI continuations trick for doing this. These are not really good solutions for me, however, as I would not necessarily have control over which VM or platform my code would run on. (Indeed any bytecode manipulation system would suffer similar problems -- it would be best were this pure Java if possible. Runtime bytecode manipulation would restrict me from using this on Android, for example.)

So does anybody have any pointers? Is this even possible? If not, will it be possible in Java 7?


Edited to add:

Just to ensure that confusion is contained, this is a related question to my other one, but not the same. This one is looking for an existing implementation in a bid to avoid reinventing the wheel unnecessarily. The other one is a question relating to how one would go about implementing coroutines in Java should this question prove unanswerable. The intent is to keep different questions on different threads.


Further edited to add:

The answer is selected. Some commentary, however, is in order. The library pointed to is not a coroutine library, so it technically doesn't answer my question. That being said, however, it has two edges over the Google Code project linked to above:

  1. Both solutions use bytecode manipulation, but the selected library allows static bytecode manipulation which renders it usable in Android and other non-compliant JVM stacks.
  2. The Google Code project doesn't do full coroutines. While the answer's library doesn't even do coroutines at all, it does something more important: it provides a good, foundational tool for rolling my own full-featured coroutines.
Cockaleekie answered 17/5, 2010 at 3:3 Comment(4)
See also related question https://mcmap.net/q/226054/-continuations-in-javaSantana
Consider also Kotlin coroutines: kotlinlang.org/docs/reference/coroutines.htmlSantana
See also How are coroutines implemented in JVM langs without JVM support?Santana
As mentioned above, it may be worth taking a look at Kotlin coroutines : Kotlin is interoperable with Java and Kotlin can also be used on Android.Ultrasonic
S
18

Javaflow is a continuation implementation, it will probably let you do that. It uses bytecode manipulation though.

Anyway, it feels like you're trying to do OOP with plain C. It's doable but it doesn't mean you should do it.

Slowwitted answered 17/5, 2010 at 6:14 Comment(2)
Yes, continuation libs will allow me to make full-featured coroutines on top. Thanks for the pointer.Cockaleekie
OK, looking closer at this one, it uses bytecode manipulation but a key feature is that this bytecode manipulation can be done statically. This means that it could be used on non-compliant JVM stacks (like Android's) albeit with a performance hit. Nice catch. Thanks!Cockaleekie
H
11

The Kilim framework implements coroutines by using byte code rewriting. I've used it myself to implement light-weight processes in Erjang, and it is very stable and surprisingly fast for the amount of bytecode rewriting that goes on.

Kilim's coroutines interact by using mailboxes, so I use the framework to model Erlang actors. But it can just as well be used to do coroutines in a shared memory model.

Homemaker answered 25/5, 2011 at 7:17 Comment(0)
S
9

What do you think of this continuations library written by Matthias Mann? I have copied the pros and cons from the creator's web site to facilitate discussion. It is important to look at the tests in the source code to see beyond the one example on the web site.

http://www.matthiasmann.de/content/view/24/26/

Lets start with what you get:

  • Write simple sequential code - you no longer need to create state machines by hand
  • No Threads are created or needed - no multi thread synchronization issues
  • No garbage creation from code execution
  • Very small runtime overhead
  • Only suspendable method calls are changed - all calls into your standard library (like java.util.* etc) are not affected at all.
  • Full serialization support
  • You can store the execution state of coroutines as part of your game state in your save game without any additional code. This of course requires that your classes and data types which you use in your coroutines are serializable. Full support for exception handling and finally blocks
  • Offline preprocessing does not slow down you application load time Of course runtime instrumentation is also possible.
  • Very small runtime library - less then 10 KByte (uncompressed JAR) BSD License

With all these great features - you may be asking for the drawbacks. Well there are of course a few drawbacks:

  • Constructors and static initializers can't be suspended
  • Suspendable methods can't be synchronized or have synchronized blocks
  • You need to download ASM3 library to run the instrumentation task
  • You can't call suspendable method with reflection

The synchronization issue can be worked around by putting code which requires the use of synchronization into it's own method.

Salt answered 14/1, 2011 at 0:58 Comment(5)
Interesting. It does bytecode manipulation to do the trick (so no using it on Android, for example) but it does everything else needed. Thanks for the pointer.Cockaleekie
To quote commons.apache.org/sandbox/javaflow/tutorial.html#Preparation "There are two ways to instrument bytecode. One way is to do it statically. This means using the javaflow Ant task as a part of your build process, to enhance the classes." In the matthiasmann continuations library ASM3 is only required for the instrumentation task. The runtime library does not depend on it. It also has an Ant task to preprocess the instrumentation.Salt
I'm curious which of these instrumentation systems might permit additional classes to be loaded at runtime, either pre-instrumented or instrumenting during classloading?Volgograd
@Salt Same thing with javaflow - needs ASM only for the instrumentation. There is no runtime dep if you instrument the classes in advance.Cambogia
@Volgograd You can load other classes at runtime.Cambogia
P
6

Your requirements seem to be:

  • lightweight - not based on Threads,
  • no reliance on native code, and
  • no use of bytecode modification.

I have a nasty feeling that these requirements have ruled out all sensible strategies for implementing coroutines in Java.

Plenteous answered 17/5, 2010 at 5:39 Comment(3)
Yeah, that's my impression from my Googling. I was hoping there was things that people more expert in Java than I am could come up with that could do the job. Of your list there, the first two are non-negotiable because they basically eliminate all of the benefits of using coroutines (the first) or Java (the second). The third looks like it's the only remaining strategy possible which limits me to compliant JVM stacks. That's not that onerous a restriction, but a hassle for some situations (like Android). Thanks for the feedback so far. I'll leave this up for a bit before selecting.Cockaleekie
Actually, there's a requirement you missed that makes the Google Code project linked up to above go down a notch in usability: proper coroutines, not mere generators. It should be possible to yield to any other coroutine, not just to the calling function. I know that you can make a dispatcher class that does that work for you, but that's an added hassle that's not necessary in a real coroutine library. I may wind up rolling my own stuff here anyway if nobody's done better.Cockaleekie
lightweight - I agree but why you wrote that you don't like reliance on bytecode modification - if continuations are implemented by compiler (eg Scala, C#) they depend on one of those 2 techniques (but it's hidden not in a library but in a compiler - what's the difference? code is just code)Airlee
M
4

If you're using Java, there are 2 options available as of late 2017:

Both of these are based off of commons-javaflow -- they re-write your code at bytecode level to get things to work.

I maintain Coroutines -- The up-sides are that it's fast, it supports all major build systems, and it supports serialization/versioning of your coroutines. The down-side is that the API has a few deviations from commons-javaflow.

Vsilaev maintains Tascalate-Javaflow -- I haven't used it so I can't speak on it, but it is maintained and from looking at the examples it's API aligns closer to that of commons-javaflow.

There are also language features in Kotlin and Scala (and maybe other JVM-based languages) that let you use coroutines. But, before switching languages you should be aware that Kotlin, Scala, or whatever the JVM language du jour is today is not and will never be Java. Whatever it's doing in the background to make things work may not work when the next release of the JVM rolls around.

The folks who maintain the JDK at Oracle have a track record of using these third-party JVM languages as market research. If a high-level feature gets added to a third-party JVM language and it's popular enough, they'll incorporate it into Java. This is what's happening right now with coroutines. There's an OpenJDK project called Project Loom that aims to add coroutines to the Java language.

It's still early days for Project Loom. If you critically look through the proposal, it's a mess. I'm sure it'll stabilize as time goes on, but what we'll ultimately end up getting may be entirely different from what many of us are expecting.

To recap, your options are to either use one of the bytecode instrumentation toolkits or to switch languages. Project Loom is still in early days and there's a possibility that it may never actually get added to Java.

Multilateral answered 27/12, 2017 at 16:8 Comment(0)
S
2

the Play framework now provides continuations with Javaflow. Because Play provides so much convenience in other areas, you may want to start with it.

http://www.playframework.org/documentation/1.2RC2/releasenotes-1.2#Continuations

Salt answered 9/4, 2011 at 15:57 Comment(0)
J
2

There is a new coroutine framework library available for Java. It is implemented in pure Java, so there's no need for JNI or Java Agents running separately. It is open source and can be downloaded from GitHub:

https://github.com/esoco/coroutines

An introduction to the framework can be found on Medium:

https://medium.com/@esocogmbh/65661a379c85

Jessamine answered 1/11, 2018 at 18:49 Comment(0)
S
0

Quasar implements Go-like coroutines and channels among other features using continuations.

More details, benchmarks and links on Quasar in my another answer.

Santana answered 13/6, 2016 at 12:53 Comment(0)
J
0

There’s a way to implement native Java coroutines using a non-public API from the Project Loom. For example this is my library for Java coroutines: https://github.com/Anamorphosee/loomoroutines

Jaime answered 18/1, 2024 at 1:50 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.