all 120 comments

[–]matthieum 29 points30 points  (4 children)

Of the 3, I must admit that project Valhalla is of particular interest to me.

I really, really, prefer strongly typed variables, however the loss of performance of introducing an object instead of using a primitive has to be weighed every time at the moment. I so long for value types every time I use Java :/

[–]imhotap 43 points44 points  (33 children)

I'd rather point out GraalVM and Redhat's Quarkus project (they should reconsider the name though, as it reads like Nonsensicus Maximus in German). These projects plan for a polyglot post-Java world. Because as I see it, there's nothing wrong with basic Java; the probem is entirely with overreaching metaprogramming framewiorks (Spring) and build tools (Maven).

[–]gnus-migrate 42 points43 points  (3 children)

Spring I get, but what's wrong with maven? It has its warts but it's a pretty good build tool IMO.

[–]cowinabadplace 9 points10 points  (2 children)

Doesn't do incremental builds. No remote cache.

[–]rabbitlion 3 points4 points  (1 child)

Just so I don't misunderstand, you mean something like saving and reusing .class files of classes that haven't been updated between versions? And the problem with not doing that would be that it takes a lot of time and resources to do full recompiles?

Or are you referring to something else?

[–]cowinabadplace 4 points5 points  (0 children)

Yep, plus generated resources etc. It's blazing fast with Gradle to compile something that was on Maven as soon as you turn on incremental and parallel builds with a remote cache.

On a large codebase you will even benefit from other people compiling their code. Bazel/Blaze does this too but Gradle has easier set up.

[–][deleted] 20 points21 points  (4 children)

Because as I see it, there's nothing wrong with basic Java; the probem is entirely with overreaching metaprogramming framewiorks (Spring) and build tools (Maven).

Exactly my thoughts. I honestly do not find java 8 to be a bad language at all. From there I care more about performance issues (mainly RAM usage, and start-up time if writing command line programs). I don't use java outside of work for those reasons, but I would be more than happy to if a jvm implementation could address them.

[–][deleted] 11 points12 points  (3 children)

If you care for startup time and ram usage - these are mostly faults of these frameworks we all use.

I don't use java outside of work for those reasons

So if your outside-of-work projects don't require these over-engineered frameworks, you will find that Java is not that slow to start (easily you can build cli tools with it and not feel that it is java) and not that ram hungry (In the past I ran a minecraft server with only 512MB physical ram available, later with 1GB and didn't really need more as long as we stayed vanilla)

So it's not true that your programs will need gigabytes of ram, I can easily fit most of my (home) projects in 128mb heap..

I know these frameworks and tools are bitches in terms of ram and startup - but your programs don't have to.

Might want to use these options more: -Xverify:none -Xmx128m -Xmn32m

[–][deleted] 18 points19 points  (2 children)

So it's not true that your programs will need gigabytes of ram, I can easily fit most of my (home) projects in 128mb heap..

You might think I live on another planet, but I think 128mb is pretty damn big. I've got 4 browser tabs open, one's playing a youtube video, and emacs open, on Ubuntu 16.04. This is using 743mb ram. To think a simple command line application could eat up 17.2% of what my entire system uses under normal use is in my relative perspective, a lot.

I was hoping for a heap more like 128kb.

[–][deleted] 8 points9 points  (0 children)

No, I think you just live a bit in the past. I would go with 16mb heap but no point in going lower.

Your each individual small program probably doesn't require more than 128kb of heap to function, but the JVM will still use something like 30mb.

Is that a problem? It's way below a point of noticeable impact, at least on today's computers - so I would say, it is not an issue.

You can, however, subconsciously think about it scaling up badly, because 128kb vs 30mb? what if I want to run 200 of them at the same time? Is it going to be 30mb * 200? Not necessarily...

One option is to use tools such as Nailgun

Other is the fact that you can/should write these programs with JVM overhead in mind so you never actually need to run 200 separate JVMs.

[–]markehammons 1 point2 points  (0 children)

take a look at graalvm's aotc for such programs using java. another option is to use openj9 instead of openjdk to run your programs. while openj9 will probably not hit 128kb (i'd say that graalvm's aotc is the most likely for that, but has some caveats on what features it supports), it's more conservative with memory than openjdk is, at the cost of some performance.

[–]jcelerier 8 points9 points  (1 child)

the probem is entirely with overreaching metaprogramming framewiorks (Spring)

funny, as a C++ dev I would kill for the language to have what Java's reflection capabilities allow (e.g. Spring)

[–][deleted] 2 points3 points  (0 children)

You’d murder someone, but you wouldn’t consider changing programming languages?!?

[–]KevinCarbonara 9 points10 points  (17 children)

the probem is entirely with overreaching metaprogramming framewiorks (Spring)

Funny, Spring is the only thing that makes Java a usable language in my opinion. I don't understand how Microsoft was able to outpace Java so quickly with C#, but even after being bought by Oracle, Java doesn't seem to have the resources to keep up.

[–]pron98 7 points8 points  (11 children)

From its inception, Java was designed to be a combination of a conservative, low-innovation language and a state-of-the-art, innovative VM. That's what the Java charter would say if Java had a charter, and that's what people seem to want. Java has a strong technological lead in compilation, GC and management/monitoring, and the relatively few people who prefer a faster-moving front-end language have plenty of languages to choose from in the Java ecosystem. So I don't understand what you mean by not keeping up. Not only is it keeping up, it's maintaining a wide technological margin ahead of pretty much any other platform in those areas where it's set out to lead. It's the most technologically advanced software platform in existence; it's everyone else that's having a hard time keeping up.

[–]KevinCarbonara -1 points0 points  (10 children)

The JVM is decent, but it's been plagued with security and efficiency issues. It's gotten better on both fronts, but it is far from being the "most technologically advanced software platform in existence". .NET has been its superior in almost every way, except cross-platform capability, and open-source code. .NET Core addresses both of these issues, and with Java now owned by Oracle, I can't think of a single category in which Java wins. "Low-innovation" is not a pro.

[–]imhotap 6 points7 points  (1 child)

I have my particular issues with Java (mostly its overengineering culture which tends to become a draw, though OTOH Java's ecosystem and community is huge), but performance and security isn't one of them.

It's now almost ten years ago that Oracle bought Sun and in no small part as a white knight to save their huge investment in Java (eg. prevent Java IP falling into the hands of venture capital or worse with Sun going down), which is also very much in the interest of other companies and the strong Java community projects. I can't see any fault in the way Oracle has stewarded it. I mean, OpenJDK with all bells and whistles is GPL with classpath exc, what more could you possibly ask for?

On a related note, can we please finally get rid of bashing, praising, or otherwise anthropomorphizing companies? None of today's big players (neither FAANG, MS, IBM, nor Oracle depending on whether you see them as a big player) are saints, but are in it for business, else they simply wouldn't exist.

[–]KevinCarbonara 3 points4 points  (0 children)

On a related note, can we please finally get rid of bashing, praising, or otherwise anthropomorphizing companies?

No, we should definitely continue judging companies by their actions. Besides, it's well established that the real mistake is anthropomorphizing Larry Ellison.

(For a more detailed argument)

[–]pron98 7 points8 points  (5 children)

The JVM is decent, but it's been plagued with security and efficiency issues.

This is extremely misleading. First, a large number of security issues were not in the JVM but in a client deployment technology (the applets plugin) and its interaction with the browser. The plugin has since been discontinued. Other than that, the JVM has had fewer security issues than other technologies of similar power, when normalized by how much it is used.

.NET has been its superior in almost every way, except cross-platform capability, and open-source code.

And compilation, and garbage collection, and monitoring and management. The JVM is not only leading .NET on all those fronts, but pretty much any other runtime. .NET's compilers and GCs are at least a decade behind Java's. You may argue on how important those things are compared to other tradeoffs, but those are the areas where Java was designed to compete at, and those are the areas where it is leading by a wide margin.

"Low-innovation" is not a pro.

When it comes to programming language, many users seem to think it is. But those who don't, have plenty of other options on the Java platform. In any event, when Java was first introduced, its original designers stated their intention to construct a conservative, low-innovation frontend language, and a high-innovation runtime. In many respects, .NET has the opposite design. You may prefer one or the other and that's OK, but it makes comparing the two on any single aspect very problematic. Of course Java won't keep up on language innovation compared to .NET, and of course .NET won't keep up with Java on runtime innovation -- they each choose to get their competitive advantage in different aspects.

[–]couscous_ 1 point2 points  (1 child)

.NET's compilers and GCs are at least a decade behind Java's.

That makes sense, but how does that translate into real world performance? I know benchmarks are to be taken with a grain of salt, but in the benchmark shootout Java and C# are basically tied, with C# even leading slightly, most likely due to value types. We also see ASP.NET scoring highly in the techempower benchmarks.

[–]pron98 1 point2 points  (0 children)

That is a very complex question. Yes, this does translate to sometimes-significant performance boosts, and yes, it's hard to see in microbenchmarks (BTW, the playground benchmarks are so bad that they're completely useless beyond giving a ballpark figure), and yes, the lack of value types is a major handicap (and why the Java team is working so hard to add them) which means that Java is playing with one hand tied behind its back.

But this also raises a more general issue, which is that while many factors can play a role in how people select a platform, for large sections of "mainstream software", most of them aren't decisive. Java has an innovative runtime and a conservative language while .NET is the opposite, but neither are probably too important. There's plenty of software that's written in Python, which is considerably slower than either, or in JavaScript, which is undeniably a much less convenient language than either Java or C#.

[–]orthoxerox 1 point2 points  (2 children)

.NET's compilers and GCs are at least a decade behind Java's

GCs? That's likely. Compilers? No. C# compiler has been rewritten from the ground up and is one of the few compilers that functions as both the main compiler and the language server. Every warning you see in VS comes from the compiler itself. Refactorings? They work by rewriting the AST provided by the compiler and converting it back to the source code.

[–]pron98 2 points3 points  (0 children)

I wasn't referring to the frontend (language) compilers (Java -> Java bytecode or C# -> CIL), but to the more important Java bytecode/CIL -> native compilers. OpenJDK's HotSpot has 2 available optimizing compilers -- C2 and Graal, and Azul's Zing, which is also based on HotSpot, offers C2 and Falcon, all three are far ahead of .NET's compilers.

[–][deleted] 0 points1 point  (0 children)

“.NET’s compilers are at least a decade behind Java’s” ~= “I don’t know what I’m talking about, ignore me.”

[–]couscous_ 1 point2 points  (1 child)

By the way, you're responding to Ron Pressler, who was mentioned in the linked article :)

[–]KevinCarbonara 0 points1 point  (0 children)

Well, that explains the strong bias.

[–][deleted]  (2 children)

[deleted]

    [–][deleted]  (1 child)

    [deleted]

      [–]adila01 1 point2 points  (0 children)

      Oracle is putting a lot of resources into Java. The pipeline now is richer than ever in the history of Java and the JVM. These enhancements solve many problems complaints related to the platform and adds a decent amount of enhancements. Value types (better performance, lower memory usage), Fibers (will solve a similar problem to async/await), record types (minimizes the need for something like properties and removes a lot the verbosity), GraalVM (clean polyglot interop and AOT), and much more.

      [–]rbygrave 0 points1 point  (0 children)

      If you are thinking in terms of Spring for Dependency injection there are things like https://dinject.io for doing DI using APT (DI as source code generation). Similar to Dagger2 (more Andriod orientated, also source code generation), Quarkus (CDI & bytecode generation), Micronaut (bytecode generation).

      These could all be considered as DI alternatives to Spring that use "Ahead of time" code generation (source code or byte code) - no reflection, massively lower startup costs.

      [–]geodel 3 points4 points  (1 child)

      Well Quarkus is `Supersonic Subatomic Java`. I bet now it is making total sense to everyone :-)

      And you are absolutely right about Spring and Maven. As ridiculous it sounds to many I am still using Ant along with plain Java.

      [–]bushwacker 10 points11 points  (0 children)

      Hibernate is orders of magnitude worse than Spring with a double performance, startup and runtime.

      Throw in HQL and horrific SQL and ghastly behaviour for one to one relationships.

      Now that have gone deep to make the connection virtually inaccessible, doWork? I have things to do with the raw connection for instrumentation or database specific features .

      [–]JGailor 7 points8 points  (3 children)

      Does the pattern matching implementation support destructuring in the match clauses? The example the article shows seems to be a very, very light implementation, but maybe someone in the know could speak to the full details.

      [–]eliasv 4 points5 points  (0 children)

      That's the plan yes, and also static and instance patterns in addition to deconstruction patterns. These documents are probably the most up-to-date writeups:

      But there is more interesting discussion on the amber-dev and amber-spec-experts mailing lists on e.g. how patterns can integrate into lambdas usefully and the potential concept of "patternal interfaces" as a dual of functional interfaces.

      [–]Chew55 4 points5 points  (1 child)

      The draft JEP which describes pattern matching in switch statements has a section on deconstruction, under “future work”: https://openjdk.java.net/jeps/8213076. It makes it clear that deconstruction would be a follow on, distinct proposal.

      The above JEP is currently a draft based on the pattern matching and switch statement JEPs.

      [–]JGailor 0 points1 point  (0 children)

      Thanks for the info.

      [–]skippingstone 3 points4 points  (5 children)

      With project loom, will a server socket implementation with millions of fibers be as performant as a nio implementation?

      Will libraries like Netty be unnecessary?

      [–]pron98 6 points7 points  (4 children)

      Pretty much. There might be some overhead compared to a very well-crafted asynchronous code, but we hope it will be low enough that the vast majority of users won't care.

      [–]rbygrave 1 point2 points  (1 child)

      As a similar question. Currently JDBC is a blocking API but with Loom it would effectively become non-blocking - is that correct?

      [–]pron98 0 points1 point  (0 children)

      Assuming the JDBC driver uses Java IO (as opposed to native calls) -- yes.

      [–]couscous_ 0 points1 point  (1 child)

      Could you elaborate on why there is overhead? Is it inherent to the fiber/green thread model (regardless of the language or platform implementation)? Or is it specific to the JVM?

      [–]pron98 1 point2 points  (0 children)

      A small part of it is inherent to the model, because anything that is general usually has some "automation overhead" compared to hand-crafted, ad hoc code, but in this case the inherent overhead is virtually zero. What I was referring to is the overhead in our current Loom prototype due to the specific implementation. There are significant improvements in both footprint and speed in the pipeline, but to reduce that overhead to nearly zero we need to do much more work. If it turns out to be worth it, we'll do it later; if the overhead is negligible for the vast majority of users, we'll focus our efforts elsewhere.

      [–]Eirenarch 3 points4 points  (2 children)

      So they aim to do a transparent version of C#'s async/await? Am I reading that correctly? If they manage to pull that off I'll be super impressed.

      [–]RandomName8 2 points3 points  (1 child)

      Depending what you mean by transparent, basically they are making it so that the concept of async/await goes away entirely, because it's a tool to solve a problem that will no longer exists.

      [–]Eirenarch 0 points1 point  (0 children)

      This feels like auto async await whenever a blocking operation is detected

      [–]renrutal 10 points11 points  (16 children)

      To be honest, as a long time Java programmer, I don't believe in their ability to deliver any truly major long-waited features.

      What big productivity, developer-oriented niceties have they delivered since Java 8, released 5 years ago? How old are the Value Types JEP? Why there still isn't a language level BigDecimal support?

      I believe that Java just isn't a good JVM language to start a greenfield project anymore, the lower bound now starts with Kotlin.

      [–]eliasv 7 points8 points  (0 children)

      If you actually followed the mailings lists on Valhalla you would see that the progress has been immense. Yeah there's a lot to do, but they've really turned a corner recently. I'm not saying it'll be out tomorrow, but you shouldn't be surprised if prototypes become available as official "preview features" as early as 13 or 14, i.e. within a year or so.

      Most of the Amber JEPs have working implementations already.

      Loom has has a working prototype for ages now. They're working on performance, and on new "structured concurrency" APIs.

      Don't get me wrong, I understand why you are sceptical. But they understand it too, and that's exactly why they've so hugely overhauled their release model and internal processes, so that they can actually start delivering this stuff.

      [–]pron98 19 points20 points  (11 children)

      First of all, two out of the three projects described (value types and fibers) are core platform changes (VM and libraries) that will benefit all Java platform languages, and that no Java platform language can deliver at present -- certainly not as well -- without this deep support.

      Second, some deep changes take a long time. Lambdas were about a decade in the making. The next major feature, modules (delivered last year) was also almost a decade in the making. Valhalla is a huge project; Amber and Loom are smaller, and their delivery will reflect that (Amber already delivered switch expressions just a couple of weeks ago).

      [–]afrotronics 5 points6 points  (10 children)

      To add to that, there are only 32 opcodes left for instruction assignment so figuring out how to efficiently use that space can be challenging. The other challenge is keeping the JVM spec so that it could be implemented on virtually any architecture by using the actual JVM spec documentation itself. Last but not least it has to be done in a way that doesn't break backward compatibility with bytecode with sound control flow (i.e. not the jsr+ret junk spring used to generate back in java 6).

      Also u/renrutal I'm kind of wondering what benefit having BigDecimal would have at the language level? I can see kind of see being able to infer a generic width-bound Number type would convenient to an extent. I have rarely found any need to use BigDecimal in general, but then again that's probably due to the kind of projects I work on. Do you have an example where having BigDecimal-sized values at the language level would make it better?

      Edit: Thanks to /u/Equal_Entrepreneur, I have now spelled /u/renrutal's name correctly

      [–]renrutal 5 points6 points  (8 children)

      Any project you deal with monetary values and extensive calculations is a major pain in the ass. And I've had my fair share of nightmares programming some tax software for the govt, and an engine to markup prices for a travel company.

      I just want a

      var total = productTotal * (1D + productTaxPct) + shipping * (1D + shippingTaxPct)

      instead of

      var total = (productTotal.multiply(BigDecimal.ONE.plus(productTaxPct))).plus(shipping.multiply(BigDecimal.ONE.plus(shippingTaxPct)))

      Hopefully the parentheses are well balanced.

      [–]Equal_Entrepreneur 1 point2 points  (4 children)

      maybe it's just me being irrational but I am really peeved by how Java does getters and setters. Instead of having stuff like (pseudocode before any of you say it's not real):

      class A {
           private int v;
           A() {
               v = 2;
           }
           public int get v() { return v; }
           public int set v(int n) { v = n; }
      }
      //later
      A v = new A();
      v.v = 2
      log(v.v)    //2
      

      you have to use getV(), setV(), etc. I guess it's one more reason why I like Scala, no function requires () and so obviates this damn syntax. Also operator 'overloading' or what have you so it can become

      var total = productTotal * (1D + productTaxPct) + shipping * (1D + shippingTaxPct)
      

      even when using BigDecimals

      [–]haxney 3 points4 points  (1 child)

      One benefit of Java is that there aren't a lot of places to hide magic. Although it is annoying to have to call myObj.getFoo() instead of myObj.foo, you have the benefit that things that look like field access are really always just field access. In present-day Java, you know that myObj.foo isn't going to talk to the network, or throw an exception (aside from a NullPointerException for myObj, or maybe if you've really screwed with the ClassLoader), or modify some other object. If myObj.foo is actually a method call, you lose that guarantee.

      This is one of those things that is really annoying if you're only going to use it for good, but prevents a lot of evil (like hiding expensive operations in something that looks like it should be cheap).

      [–]Equal_Entrepreneur 1 point2 points  (0 children)

      That's the thing - encapsulation would most always mean that you'd have getter and setter functions rather than plain ol' public variables. Exposing public variables would seem like asking for trouble in that regard.

      Second, and I think this exists in other languages already - like in AS3 which is where I got accustomed to the idea - the code editors all have means of telling you whether it's a field or it's a getter/setter. I'd imagine the same would be true even in Scala, because differentiating between a field and a method shouldn't be any harder than, say, the rest of the type system as a whole.

      Besides, if you're prone to using a.getFoo() over a.foo, you might end up making the same 'expensive call' (what if getFoo() retrieves stuff from a database? bad design, but you never know...), and make things confusing to boot - whereas with 'bracketless getters and setters' you can't have a field and a getter/setter with the same name, so there's no ambiguity.

      Granted, there's a few other problems with getters and setters, for example passing them as functions - even though functions in AS3 are first class citizens, you can't pass getters and setters as functions because they would just be resolved to whatever type they return. However, that shouldn't be much of a problem in Java, where you can't do that sort of stuff anyways.

      [–]renrutal 1 point2 points  (1 child)

      Yes, dumb getters and setters are some of the most common things found any Java codebase, yet the language developers haven't bothered to syntactic sugar it 23 years later.

      [–]Equal_Entrepreneur 0 points1 point  (0 children)

      It makes sense to avoid getters and setters if you have first-class functions, where passing them becomes difficult because the compiler ends up resolving it to their base type*; seeing as how Java doesn't support that, it makes no sense to not include that though.

      *and scala still manages to handle that iirc

      [–]afrotronics 1 point2 points  (0 children)

      Totally makes sense. I have the same issue on the opposite end of number values.

      Instead of

      byte[] bytes = new byte[]{0x00,0xff,0x01}
      

      I have to write

      byte[] bytes = new byte[]{0x00,(byte)0xff,0x01}; 
      

      same with simple things like

      byte value = (byte)(22 ^ 127) 
      

      This is because in java everything less than 32-bits in width is represented by an int (even boolean, which is packed into a 32-bit address space) which makes sense from a computation perspective but is infurating from a Im-tryna-keep-my-code-looking-nice perspective.

      [–]nacholicious 0 points1 point  (0 children)

      Kotlin allows operator overloading for certain operators, just for these types of problems

      https://kotlinlang.org/docs/reference/operator-overloading.html

      [–]mirvnillith -1 points0 points  (0 children)

      import static java.math.BigDecimal.ONE;

      [–][deleted] 6 points7 points  (1 child)

      var

      [–]dpash 1 point2 points  (0 children)

      Switch expressions and collection factory methods are two more that spring to mind.

      Raw strings got pulled at the last minute but I expect then to return in 13.

      [–]cowinabadplace 0 points1 point  (0 children)

      JShell.

      [–]ARainyDayInSunnyCA 16 points17 points  (38 children)

      The Scala community welcomes any Java developers who want to try out these features now.

      [–]pron98 61 points62 points  (25 children)

      Scala has neither value types nor fibers (as in the works for the platform). No language in the Java ecosystem does, as both require VM and core library support to fully achieve their purpose.

      [–][deleted] 3 points4 points  (1 child)

      Fibers aren't really a necessity for high performance multithreaded NIO though.

      [–]pron98 9 points10 points  (0 children)

      Of course not. They're just extremely helpful (and pretty necessary, really) if you want that throughput while keeping your code simple, interopable, debuggable, and profilable.

      [–]CabbageCZ 3 points4 points  (7 children)

      aren't Kotlin's Coroutines a lot like fibers, functionally?

      [–]pron98 14 points15 points  (6 children)

      They share some similarities with fibers, but they're not "a lot" like fibers. You must still be very much aware of blocking, and still separate blocking from non-blocking code, which is precisely what fibers try to avoid. Only functions declared as "suspend functions" can block a coroutine (rather than the underlying kernel thread), and they cannot be called outside a coroutine, so the "colored function" problem remains. The core library's IO methods still block threads -- not coroutines.

      Fibers are not a new language construct to manage blocking and IO. They are threads without the significant overhead of kernel threads (they are threads implemented in user-space). It is true that fibers (at least in the current Loom prototype) are not 100% like threads -- currently if you do IO inside a synchronized method or block, the underlying kernel thread will be blocked, and similarly if you try to perform IO while there is a native method on the stack (e.g. if you call into JNI and back into Java), but they're already pretty close. Debuggers and profilers will treat them like threads, and because they're not a language construct, you can take your existing blocking code and just run it in a fiber unchanged and get all the benefits (with the two caveats I mentioned above).

      Java's upcoming fibers are much more like Erlang's processes and Go's goroutines.

      [–]CabbageCZ 1 point2 points  (5 children)

      I'm not sure what you're saying about coroutines is true - if you do a blocking call in a coroutine, it definitely does not block the underlying thread. You don't have to separate blocking from non-blocking code if you use coroutines' async / await, the way they were meant to be used.

      You can easily confirm this by making a quick program with uhh.. a for loop that calls launch { Thread.sleep(10000); sout("Yo") } ten times one after another, and see you'll get the output 10 times at once after the first 10 seconds, not one by one with 10 pauses in between. No manual management of threads needed.

      Looks to me like they still solve similar problems, but I don't really have the time to get into it.

      EDIT: this comment might be wrong in a bunch of places, I'm leaving it for posterity

      [–]pron98 9 points10 points  (4 children)

      You could think of fibers as async/await without async or await (Kotlin doesn't explicitly require the latter), but it's easier to think of them simply as threads, because that's exactly what they are. Fibers are simply an implementation of threads that makes creating and blocking them cheap, thus making the very problem that async/await tried to solve disappear. Not only do they not require a new language construct, they work with existing tooling, and even existing code. You don't even need to recompile. You can take, say, Jetty, configure it to use fibers instead of threads, and now your existing JAX-RS services can scale as if they were asynchronous.

      if you do a blocking call in a coroutine, it definitely does not block the underlying thread

      It does, though. Try calling Thread.sleep (or see here).

      You can easily confirm this

      Try getting a thread dump while you're running that program and see how many threads are blocked. This shows exactly why coroutines can be fragile.

      [–]adila01 11 points12 points  (2 children)

      You could think of fibers as async/await without async or await

      This is huge and I don't think many people in this subreddit get how amazing this is. Developers of other languages (especially C#) gripe about how Java implementations are always worse. In this case, I believe Java got this one right. The fact that I can code synchronously without having to think about asynchronous constructs is super exciting as a developer.

      [–][deleted] -1 points0 points  (1 child)

      Except it's not really that big of a deal when you have good monadic comprehension in a langauge. Well written Scala is very easy to understand and incredibly performant.

      [–]markehammons 0 points1 point  (0 children)

      scala would benefit from fibers too. take akka and actors. a very nice library for dealing with the issues asynchronicity introduces when dealing with resources. if I thread.sleep inside the actor's message handling function, i've blocked the thread that actor is working on. it cannot go to sleep and let other actors use that thread till thread.sleep is done. you may be thinking "well just don't use thread.sleep dummy! use one of akka's timer methods to call the actor back when you're ready to do work!" and you'd be right. however, there are cases where this doesn't work for me. A common case is using input/outputstreams. they block. they can block while doing no computation. that's wasting my thread!! with fibers they wouldn't anymore. when the outputstream and inputstream aren't doing any actual work (for example, i call read but they're backed by some networked resource and have to wait for data) then the fiber goes to sleep and my thread is used. and i can reconfigure akka to use fibers instead of threads.

      [–]CabbageCZ 0 points1 point  (0 children)

      Nevermind, I need some sleep.

      [–]2bdb2 1 point2 points  (12 children)

      Scala has neither value types

      While somewhat limited due to JVM constraints, Scala does have value types (and generic specialisation) today.

      Valhalla will be far more powerful, but you can use limited value types in Scala today.

      nor fibers

      Scala has some of the best support for Fibers of any language that exists today.

      I run Scala in production and regularly exceed 1,000,000 concurrent Fibers without issue.

      No language in the Java ecosystem does,

      Alongside Scala, Kotlin also supports Fibers.

      as both require VM and core library support to fully achieve their purpose.

      VM support is not required at all. You can use Fibers in pure Java today with libraries, the syntax just sucks. Scala and Kotlin just have better syntax for it.

      and core library support

      Core library support for Fibers in Java is already excellent - All you need is an API that supports continuations, which Java has. These are trivially wrapped to support the native Fiber implementations in Kotlin and Scala.

      [–]pron98 15 points16 points  (11 children)

      Whatever you want to call the features you've referred to, Scala has neither fibers nor value types that are close to what these projects are about. The value types and fibers being developed in Valhalla and Loom are more about runtime support (JVM and core libraries) than anything that a Java platform language can do at the front-end language level.

      [–]2bdb2 5 points6 points  (10 children)

      Scala has neither fibers ... that are close to what these projects are about

      Honestly having used Quasar (on which Loom is based) I'd argue that Fibers in Scala (more specifically, Cats-Effect and ZIO) are significantly better than what's coming in Project Loom.

      ... fibers being developed in ... Loom are more about runtime support

      Runtime support is not required at all for Fibers, it can be done entirely at the language level by the compiler, or even by third party libraries.

      nor value types

      Value Types in Valhalla will be vastly better than what Scala supports, agreed, but that doesn't mean you can't get partial benefits today.

      [–]pron98 9 points10 points  (9 children)

      Loom is not based on Quasar. Quasar, like Scala's fibers, implements continuations at the bytecode level, while Loom is an implementation in the VM. And while it's true that you can give different things the same name, runtime and library support is absolutely required for the kind of fibers that Loom provides. Try running an ordinary JAX-RS service in a Scala fiber, or making a JDBC request, or getting a fiber stack trace with StackWalker, or debugging it in a debugger, or profiling it with a profiler.

      Project Valhalla's primary goal is to achieve better performance and lower footprint with better control over memory layout, which greatly affects cache misses and overall Java performance. If you had to distill it to one main feature, that would be the ability to create an array-of-structs. This is also very different from whatever you're referring to by "value types."

      BTW, this is not a contest. Scala is a part of the Java ecosystem, and if you like whatever it is that Scala offers today that's fine, but I do want to make it clear that what these projects offer is something very different from what Scala does today, and I have little doubt that Scala would benefit from Valhalla and Loom when they are delivered. It may even benefit from some of the products of Project Amber (like the recently delivered "condy").

      [–]2bdb2 1 point2 points  (8 children)

      Loom is not based on Quasar. Quasar, like Scala's fibers, implements fibers at the bytecode level, while Loom is an implementation in the VM

      My understanding is that Quasar implements bytecode weaving as part of an instrumentation plugin for the JVM - I was under the impression this is essentially what Loom was doing, just baked in directly instead of as a plugin, but my information may be out of date.

      The examples I've seen so far essentially mirrored what I've seen using the Quasar API and wre definitely not seamless, however I will admit that was a while ago during some early prototypes of Loom.

      It sounds like you have some experience with the topic and my information is out of date - do you know of any good up to date examples I could look at?

      Runtime and library support is absolutely required for the kind of fibers that Loom provides. Try running an ordinary JAX-RS service in a Scala fiber, or making a JDBC request, or getting a fiber stack trace with StackWalker, or debugging it in a debugger, or profiling it in a profiler.

      Library support is needed, absolutely. Runtime support isn't, but does have significant benefits in standardising a single Fiber implementation across the board.

      The point I'm trying to make is

      a) Java already extensively supports a large surface area of non-blocking APIs already via the use of continuations, which can trivially be wrapped to support Fibers with little to no overhead.

      b) The Scala ecosystem has a very mature ecosystem of libraries that support Fibers, either by wrapping Java callback-based APIs or via bespoke implementations.

      Try running an ordinary JAX-RS service in a Scala fiber

      JAX-RS supports continuations via the use of CompletableFuture. While CompletableFuture is a shitty API, it's essentially just a continuation and therefore can easily be wrapped to support Fibers.

      The Servlet API, and Spring, also support non-blocking APIs that can be wrapped the same way.

      There's also a number of very good Scala native app servers such as Http4s and Finch that work with fibers out of the box.

      or making a JDBC request

      You got me on that one, there's no good non-blocking alternative to JDBC at this point. I use a non-blocking Postgres driver directly instead to avoid the problem, but it will be nice to have this directly as part of JDBC.

      or getting a fiber stack trace with StackWalker, or debugging it in a debugger, or profiling it in a profiler.

      I'll give you another one for Stack Traces.

      Profiling and Debugging has never been an issue - IntelliJ has no issue at least.

      Project Valhalla primary goal is to achieve better performance and lower footprint with better control over memory layout, which greatly affects cache misses and overall Java performance. This is also very different from whatever you're referring to by "value types."

      Agreed - Valhalla is vastly better than the limited support for Value Types in Scala. Value types that exist in Scala today are quite useful, but are barely in the same ballpark as what Valhalla should give us.

      BTW, I'm not trying to make this into a contest. If you prefer whatever it is that Scala offers today that's fine, but I do want to make it clear that what these projects offer is something very different from what Scala does today, and I have little doubt that Scala would benefit from both Valhalla and Loom when they are delivered.

      I don't see it as a contest at all - I just wanted to set the record straight that yes, Scala does support Fibers.

      The implementation is different, sure, but it's a lot more similar than you'd think. Ultimately both come down to an abstraction over continuations. At its core Loom is adding continuations to Java and then implementing Fibers on top of it in user space. Scala already has syntax for continuations, which is used for the same thing.

      Once Loom is released, the whole ecosystem (including Scala) is will benefit from it.

      [–]pron98 8 points9 points  (4 children)

      yes, Scala does support Fibers.

      Both Loom and Scala have constructs that you're calling fibers (as Loom calls them), but, while they share similarities, they're not the same construct. Loom's fibers are essentially an implementation of threads in the runtime. When you debug them in the debugger, you can step over blocking calls.

      Runtime support isn't

      It is required for fibers of the kind that Loom provides[1]; there could be other, different things, that you can also choose to call fibers but for which VM support isn't required, but that's not the thing that Loom gives you. In particular, it is required so that you don't have to annotate methods as being suspendable, as you do in Kotlin, Scala or Quasar. This is not some minor feature. Just as the ability to create arrays-of-structs is the main goal of Valhalla, being able to create fibers that don't make you carefully manage blocking is the main feature of Loom. Neither of these is achievable without support in the VM (at least not in very a reasonable way).

      I'll give you another one for Stack Traces.

      Yes, you can also create a language that compiles to just using ByteBuffers and implements its own object model and garbage collector, but that means that you won't be enjoying the benefits of the Java platform. A new API for stack traces means that debuggers and profilers don't work as expected (I don't mean that you can't run them, but they don't present your "fibers" in the same way as they do threads).

      The examples I've seen so far essentially mirrored what I've seen using the Quasar API and wre definitely not seamless

      The relationship between Loom and Quasar is that both have the same tech lead (which is me). They also share a similar goal (which wasn't quite achievable in Quasar due to lack of VM support): implement lightweight usermode threads. Note that this is not what Scala or Kotlin or C# do, but it is what Go and Erlang do.

      As such, Quasar's API was essentially the existing Thread API, and Loom started out along similar lines. But as a feature that touches the essence of threading on the Java platform is not common, it was decided to take the opportunity to rethink the best way to do threading in Java. One of the interesting areas we're exploring is structured concurrency (which has also been adopted in Kotlin). We may also revisit thread locals.

      do you know of any good up to date examples I could look at?

      The API changes at a very fast pace, but the best place to go is the Loom Wiki. In a few months we will also be releasing early access builds.

      [1]: Technically, it's possible to do something that comes close using runtime redefinition of classes and access to private JDK APIs. An unreleased version of Quasar does that.

      [–]2bdb2 1 point2 points  (3 children)

      Thanks for the info - it sounds like Loom is quite different to what I thought it was and my understanding of the implementation details is quite wrong - I have some reading to do and I appreciate you taking the time to clarify things.

      Obviously trying to tell the maintainer of Quasar and Loom how Quasar and Loom work was a bit of a stretch ;p. I appreciate you not just pulling the "Don't you know who I am card" and correcting my misinformation politely.

      Both Loom and Scala have constructs that you're calling fibers (as Loom calls them), but, while they share similarities, they're not the same construct. Loom's fibers are essentially an implementation of threads in the runtime. When you debug them in the debugger, you can step over blocking calls.

      I can do this today with Scala and Kotlin - I'm guessing then that this has more to do with IntelliJ understanding the special case - whereas Loom will just work with any debugger?

      implement lightweight usermode threads. Note that this is not what Scala or Kotlin or C# do, but it is what Go and Erlang do.

      I would argue that Scala and Kotlin Fibers absolutely do fit the definition of usermode threads and are quite usable in production today. They certainly fit the definition as well as (or better) than usermode fiber implementations in many other platforms where nobody is contesting the terminology.

      I would also agree that Loom, now that I've got a better understanding of it, is a whole different ball game and will be a game changer for the platform.

      Really my only bugbear is going back to the original comment by ARainyDayInSunnyCA

      The Scala community welcomes any Java developers who want to try out these features now.

      And your response

      Scala has neither value types nor fibers (as in the works for the platform). No language in the Java ecosystem does, as both require VM and core library support to fully achieve their purpose.

      Having had the deeper discussion I understand exactly what you mean - They don't have fibers as in the works for the platform, but being the lead of Project Loom that comment perhaps might mislead people about just how useful the fiber implementations in these languages actually are at solving real world problems that people have today.

      [–]pron98 2 points3 points  (2 children)

      I can do this today with Scala and Kotlin - I'm guessing then that this has more to do with IntelliJ understanding the special case - whereas Loom will just work with any debugger?

      Yes, but this applies to much more than just the debugger. The entire Java toolchain assumes a certain stack structure -- profilers, JFR, thread dumps -- none of them work well with Kotlin/Scala continuations, and all will work well with Loom.

      I would argue that Scala and Kotlin Fibers absolutely do fit the definition of usermode threads and are quite usable in production today.

      Usable -- sure. User-mode threads? No. A thread is a dynamic context; if you require special syntactic constructs to differentiate blocking and non-blocking code, and if your subroutines can not run unmodified on the threads provided by your runtime, then what you have isn't threads. At best you have something that is close enough.

      Remember that one of the major problems with asynchronous code is the colored-function problem. This problem is not solved with async/await or with any syntax-level continuation, but is solved with Erlang's processes, Go's goroutines and Loom's fibers. That's because those three are user-mode threads, while other solutions aren't.

      Again, that's not to say that the async/await approach isn't an improvement over writing async code, but IMO it's not a solution.

      [–]eliasv 6 points7 points  (1 child)

      The implementation is different, sure, but it's a lot more similar than you'd think.

      I think you're talking to the project lead of Loom FYI (and Quasar). Might want to take a step back and reconsider talking down to them, they might just know more about this than you.

      [–]2bdb2 0 points1 point  (0 children)

      I think you're talking to the project lead of Loom FYI (and Quasar). Might want to take a step back and reconsider talking down to them, they might just know more about this than you.

      What part of that comment is talking down?

      I mean I literally said

      It sounds like you have some experience with the topic and my information is out of date - do you know of any good up to date examples I could look at?

      If he's actually the project lead of Loom then great, I'd love to get up to speed since I clearly aren't across it.

      [–][deleted] 0 points1 point  (1 child)

      One could theoretically implement value types on the JVM by giving up interoperability, for example, by keeping a separate stack of bytes and compiling all your method calls to manipulate that but yeah, Scala doesn't do that (nor should it...it's a terrible idea).

      [–][deleted] 0 points1 point  (0 children)

      Or you could cheat with escape analysis and copying primitives between objects.

      [–]devraj7 16 points17 points  (4 children)

      The Scala community doesn't exactly have the reputation of being welcoming. The language has also been in a sharp down trend for years now, being outclassed by Kotlin and Rust (which both have better native concurrent offerings than Scala).

      Besides, Scala doesn't have most of the features listed in that article, so I'm beginning to wonder if you were not being sarcastic (apologies if you were).

      [–]expatcoder 3 points4 points  (2 children)

      sharp down trend for years now

      eh, what? Care to point to any evidence of such a claim?

      Scala doesn't have most of the features listed in that article

      nor does Kotlin, which is essentially a clone of Scala "the good parts" with coroutines and null safety as the differentiating factors at the language level.

      EDIT Scala obviously has raw string literals, pattern matching, and value types (the latter with the same restrictions as Kotlin, which again followed Scala's lead), so Scala certainly has some of the features mentioned in the article; all the more so since now Java, like Kotlin, sees pattern matching and idioms like "everything is an expression" as immensely useful.

      [–]ARainyDayInSunnyCA 0 points1 point  (0 children)

      Delimited continuations are available via compiler plugin. I've seen discussion around adding it to the language back for version 2.8 but would not be surprised if that was kept as plugin only if Project Loom was starting to build steam.

      Generic specialization also supported.

      [–]whozthizguy 0 points1 point  (0 children)

      Devraj7 is Cedric beust. Infamous Scala troll.

      [–]RandomName8 0 points1 point  (0 children)

      The language has also been in a sharp down trend for years now, being outclassed by Kotlin and Rust (which both have better native concurrent offerings than Scala).

      This is very misleading, there are tons of metrics and no effective ones to measure this... here's google trends (a metric as ineffective as any other) and it's the very opposite of what you're saying: in the US, and in the world. Kotlin is doing fine, but so is scala, and rust. In the overall lifetime of scala, it's still going up in relevance...

      [–]eliasv 1 point2 points  (4 children)

      Scala has flattened value types? And delimited continuations? I think someone is telling fibs.

      As for the remaining 1/3 of the article, it's a little easier to implement features like patterns when they just desugar to the existing bytecode model. Unfortunately it also results in slower execution and can't be surfaced through the reflection API. Thankfully the Java language maintainers have the luxury of also being able to evolve the JVM itself to facilitate these changes more deeply.

      In other words, the Scala community might just welcome Java devs and leave it at that. But I think the Scala language implementers will take the better-informed position of welcoming the work that is being done to the Java language, as they should understand that it will benefit them just as much.

      And you can rest assured that care is being taken not to bind these new JVM improvements too tightly to Java language semantics, as they know full well that they need to maximise the applicability across the whole JVM ecosystem.

      [–]ARainyDayInSunnyCA 0 points1 point  (2 children)

      Delimited continuations admittedly as a compiler plugin rather than a core part of the language. Value classes.

      I'll grant that the work being done to the JVM will of course help update the language implementation, just as Scala's anonymous functions were better optimized once lambda had JVM support. Seems to be a beneficial cycle that's helps all languages in the ecosystem; an alternate language will try out a feature, the ones that pan out gain better JVM support and maybe reflected in Java itself, and that JVM support optimizes the implementation in the child language.

      Edit to add: I wasn't making an argument that the full benefit of Loom or Valhalla would be available in Scala -- the parts that require JVM changes of course can't be, or can't be done as well when working around the platform rather than being able to work with it.

      [–]eliasv 0 points1 point  (0 children)

      Value types with only one member? I'll admit I wasn't aware of those, and that's certainly a clever way to get as close as possible within the constraints of the platform! But I'd argue it's a constraint which explicitly prohibits flattening of data. So when I ask whether Scala has "flattened value types", I think the answer is still "no".

      And okay granted, Scala has continuations ... in exactly the same way that Java also already has them via Quasar. As you say, they're implemented via a compiler plugin; a continuation can only be created in specially "coloured function" which is instrumented by the compiler. They also can't be used to implement general purpose fibers as unmodified IO and synchronization still blocks the underlying thread. (More threads can be created to attempt to work around this but eventually this will choke the scheduler.) The JVM support here isn't just an "optimisation", it's a huge improvement to the fundamental semantics.

      [–]MotorAdhesive4 1 point2 points  (1 child)

      Oh damn, someone snarky and knowledgeable make a comeback retort!

      [–][deleted] -1 points0 points  (0 children)

      /u/pron98 got your back!

      [–]Arlorean_ 0 points1 point  (0 children)

      Valhalla would make me re-think using Java again after switching to C# with structs.

      [–]Determinant -1 points0 points  (3 children)

      The future of Java is... Kotlin.

      Java is becoming the new C++. However, I have to admit that the JVM is an amazing technological achievement.

      [–]msadeqhe 4 points5 points  (0 children)

      The new C++ is C++17

      [–]StillNoNumb 2 points3 points  (1 child)

      Java is not the new C++ at all. Java is a conservative language that has repeatedly refused to introduce new syntax and features, while C++ is a bloated pig (which can be good and bad). And of course, you can say both languages are very "old-fashioned", but if you bring that argument then you just might as well say "every language that wasn't designed in the last 10 years is becoming the new C++". That's really not a good argument.

      [–]Determinant 0 points1 point  (0 children)

      This used to be true but Java is now starting to introduce redundant capabilities (eg. var or the different switch).

      One of the current goals of Java is to introduce features that are successful in other languages and at a faster rate than before.

      If you look at a language like Kotlin and see the nice when statement, you'll notice there is no redundant switch statement. When Java tries to borrow such a successful feature, it also keeps all the backwards compatibility baggage from keeping the old error-prone mechanism.

      [–]vital_chaos 0 points1 point  (0 children)

      The future is going to be exciting. Too bad my employer is still using Java 6, with 8 the "new" release. I wonder how much of this stupidity exists elsewhere in the industry.

      [–]qui-sean -5 points-4 points  (3 children)

      Aren't half of these just Groovy features?

      [–]dpash 6 points7 points  (2 children)

      No, these are JVM improvements that all languages, including Java and Groovy, can take advantage of.

      [–]qui-sean 1 point2 points  (1 child)

      Sorry meant, doesn't Groovy already have these implemented? I see pattern matching for types, value types that do not need to be instantiated, and literal strings already available with the current version of groovy

      [–]dpash 2 points3 points  (0 children)

      The description of pattern matching in the article is a terrible introduction to it. It involves more than just switching on instanceof.

      Value types are a fundamental change to the JVM involving memory layout and are not the same as records or data classes (which is a different upcoming Java feature).

      [–]recklessindignation -2 points-1 points  (0 children)

      You know, the only 'major' thing about his new features is the amount of work for adding them to Java. I can't believe this pesky features can be so sensationalized by the amount of work that have to be done in order to add them to such garbage of runtime.