[HN Gopher] Don't call it a comeback: Java is still champ
___________________________________________________________________
Don't call it a comeback: Java is still champ
Author : smartblondeva
Score : 210 points
Date : 2022-08-09 15:24 UTC (7 hours ago)
(HTM) web link (github.com)
(TXT) w3m dump (github.com)
| bilsbie wrote:
| I've never once enjoyed writing Java. To me that's worth a lot.
|
| To me it's always felt like some kind of assembly language humans
| shouldn't deal with directly.
| hackerlight wrote:
| Java is the perfect choice if you need something that runs really
| fast but not really really fast. It fills that niche very well.
| Cwizard wrote:
| I think Java gets a lot of flak because it is so popular within
| enterprises. And we all know what kind of code gets written in
| non-IT corporates. Add to that the fact that Java allows you to
| do a lot means a lot of crazy code was conjured up over the years
| which then had to be maintained and developed.
|
| If you apply some discipline, I think Java is a great language.
| fareesh wrote:
| I don't really write in Java these days, but when I did the
| biggest pain points for me were:
|
| - IDE: IntelliJ and before that, Eclipse, were painfully slow to
| use. Even now occasionally if I have to launch Android Studio I
| have to wait for Gradle and various other things. The entire IDE
| gets sluggish while it's doing indexing and all sorts of
| weirdness. vim integration was quite poor at the time, I don't
| know if things have changed since.
|
| - Verbosity: It always feels like I am writing boilerplate and
| long names. I remember trying to write something with websockets
| and no matter what library I picked there was a ton of
| boilerplate to write for just connecting to a socket and sending
| a message.
|
| If given a choice I'd much rather write in Python, C#, Ruby or
| even Typescript. The language feels very dated - or perhaps there
| are newer ways to do things that I'm totally unaware of.
| fenesiistvan wrote:
| IDE: Borland JBuilder was a king. I am still using it
| Websockets: you can write your own in around 400 lines of code.
| I did it. The specification/RFC is really simple. Just a few
| bits above TCP
| abadger9 wrote:
| I've used Java my entire career and i'm fortunate for it. I
| appreciate how readable the code is (unlike my experience with
| Erlang, Haskell, etc), typically i don't have foundational issues
| in the web framework (once again had some with Haskell).
| Everything works, if I need to do low latency, there's great
| libraries and resources, if i need to build a simple internal
| tool, it can be done effortlessly.
|
| I think python is the same way, the ecosystem is so rich that you
| can really do anything you want (until you get into low latency).
| 62951413 wrote:
| I believe it's unfortunate people judge the JVM ecosystem by
| Java. Scala and Kotlin are so much more attractive options if
| you write code for a living. Between this and the devolution
| from maven to gradle it's not a surprise junior developers are
| JVM-shy.
|
| I see companies downshifting to unmaintainable toys such as
| Python even in data engineering circles. It's really odd that
| mobile developers with Kotlin (and front-end ones with
| Typescript) are getting ahead of backend ones in adoption of
| modern languages.
|
| Once Loom and Valhalla get merged to an LTS the remaining
| vestiges of bad old Java will have been gone. I really hope
| Graal goes mainstream too. That will hopefully blow out of the
| water the golangs of the world. But those are platform-level
| improvements any JVM language will benefit from.
| thrown_22 wrote:
| >if I need to do low latency
|
| If the JVM is considered low latency I shudder to think what is
| high latency.
| hackerlight wrote:
| Java is pretty fast. Second most popular language in HFT. Can
| get it to a few tens of micros. Not as fast as C++ at sub 5
| micros. So good enough for many latency sensitive apps.
| bitcharmer wrote:
| All our market data feed handlers are sub 5 micro in the
| 99th. All in Java.
| _gabe_ wrote:
| > Not as fast as C++ at sub 5 micros.
|
| Try sub 5 nanos. I was curious awhile ago at how fast C++
| hash set lookup was compared to C#, and it consistently
| performed a lookup at 1 nanosecond. I tested with up to 6GB
| of data and then stopped because it was taking longer to
| generate random data then it was to run the benchmark
| 10,000 times.
|
| C++ benchmarks here[0]. It's a bit more complicated then
| just a pure lookup since I was pulling some code out of a
| larger app, but the benchmark is only measuring the lookup
| speed. I did the C# benchmarks with BenchmarkDotNet or
| something like that, I can never remember the exact name.
|
| [0]: https://gist.github.com/ambrosiogabe/66a6e2fdc77e6a600
| e570f4...
| titzer wrote:
| > and it consistently performed a lookup at 1 nanosecond.
|
| TBH I'm skeptical that you are measuring what you think
| you are measuring. There are a lot of micro-benchmarking
| pitfalls, like dead code elimination, loop-invariant code
| motion, unrolling, and other issues. Unless you actually
| looked at the machine code coming out of the compiler,
| you're measuring something you don't understand. E.g. 1
| nanosecond is roughly 3-6 instructions. That 100% means
| the hash lookup has been inlined into the benchmarking
| loop.
|
| Are your hashtables mostly empty? Really small? Lots of
| easy hits (or easy misses)? Because the slow cases
| (actually looking up) are going to be hairier and may not
| be inlined.
|
| Did you benchmark against Java's HashMap? Because it is
| also very, very, very fast for simple cases.
| _gabe_ wrote:
| It looks like caching definitely skewed the results a
| bit. You can take a look at the linked code yourself.
| Worst case was still only around 80 nanoseconds which is
| definitely slower, but still orders of magnitude faster
| than "sub 5 micros".
|
| Don't take my word for it though, you can take a look at
| the Robin Hood benchmarks[0]. Robin Hood unordered map is
| a competitive hash map that's performed much better than
| the STL for me in many cases. They average a 4 nanosecond
| lookup speed for a hash map with 2000 elements and an
| integer key.
|
| > Did you benchmark against Java's HashMap?
|
| I benchmarked against C#, which has a runtime that
| performs similar if not better than the JVM. The C# code
| was a ~~few microseconds~~ around 130 nanoseconds. Which
| is still very fast, but up to 100x slower. (And yes, this
| was _after_ warming up the code. I used benchmark dot
| net[1] here.). This is a really easy benchmark to set up.
| If you doubt me you can write a couple of benchmarks in
| under an hour and compare yourself.
|
| [0]: https://martin.ankerl.com/2019/04/01/hashmap-
| benchmarks-04-0...
|
| [1]: https://benchmarkdotnet.org/articles/overview.html
| titzer wrote:
| Did I read that right? The C# version is computing SHA256
| hashes?
| _gabe_ wrote:
| That's a link to the benchmark framework that I used. The
| C# benchmark are in a separate gist that I didn't feel
| like digging up. This is the C# benchmarks[0]. All the
| interfaces and indirection is the result of me adapting
| this from a separate comment. But the benchmark is just
| testing `HashSet.TryGetValue`.
|
| Edit: I just re-ran the benchmarks because I didn't have
| the results pasted in the snippet (which I've now done so
| I don't keep getting this wrong haha). The C# HashSet
| takes around 130 nanoseconds, not microseconds. So it's
| not orders of magnitude slower, but it is still more than
| a 2x slow down and up to a 100x slow down in the case of
| an integer key.
|
| [0]: https://gist.github.com/ambrosiogabe/ba6bd0fa80588c2
| fd2ca26d...
| 5e92cb50239222b wrote:
| Java is heavily used in high-frequency trading. I believe
| it's the most popular language after C++.
| zinxq wrote:
| Indeed. Shutoff Garbage collection completely and it can
| work. (And make sure your Java code creates no garbage -
| which is a new type of programming in and of itself)
| zinxq wrote:
| Edit: My bad - unfortunate wording. I didn't mean this as
| negative at all. It's cool (if niche) ability.
| vips7L wrote:
| Maybe I'm taking your comment wrong, why is this a bad
| thing? What other GC'd language just lets you turn it
| off?
| bee_rider wrote:
| I don't think their comment is intended to be negative
| really -- looks more like appreciative of the option,
| while cognizant of the fact that using it introduces a
| new challenge.
| bitcharmer wrote:
| It's not about turning it off. You just don't allocate on
| the hot path.
| vips7L wrote:
| Some people choose to do neither!
| https://medium.com/@jadsarmo/why-we-chose-java-for-our-
| high-...
| amusedcyclist wrote:
| Depends on the use case, but if you are working on web
| servers or other long lived processes the JVM is pretty close
| to native and can even beat native code thanks to JIT
| compilation.
| dkarl wrote:
| Agree with all of that except readability. Java has some
| language deficiencies (no first-class functions, "streams"
| missing for almost twenty years and added too late to be done
| elegantly) and some cultural norms (mutable everything, overuse
| of inheritance) that make it a chore to read most of the Java
| code you encounter in the wild, including the source code of
| the libraries you depend on. Figuring out the behavior of one
| method routinely means taking a tour through implementation
| details in three or four superclasses, factories, factory
| factories, and all the other Java cliches that are legendary
| but also absolutely real.
|
| You can do better in your own code, but you still have exposure
| to the code in the library ecosystem.
|
| Worth it, though. It really does seem like there's a Java
| library for everything.
| gavinray wrote:
| Modern Java has first-class functions, pattern matching with
| structural binding, records/pure immutable data classes, the
| whole 9 yards: static void main() {
| BiFunction<Integer, Integer, Integer> add = (Integer x,
| Integer y) -> x + y + 5; Integer result =
| addTo(10, add); Integer result2 = addTo(10, (x,
| y) -> x + y + 5); } static Integer
| addTo(Integer acc, BiFunction<Integer, Integer, Integer>
| addFn) { return addFn.apply(acc, 5); }
| Integer eval(Expression e) { return switch (e) {
| case INT(var value) -> value case ADD(var
| left, var right) -> eval(left) + eval(right)
| case MULT(var left, var right) -> eval(left) * eval(right)
| } }
| mrtranscendence wrote:
| I haven't programmed in Java since 2005, so forgive me. But
| isn't a lambda automatically converted to an object of the
| necessary single-method type? That feels a little magical
| and suggests that there really isn't such a thing as a
| genuine first-class function in Java, as there is no way to
| define a function, and no universal type to assign to such
| a thing.
| kaba0 wrote:
| First class functions are as modern as the Iphone 5.
| mrtranscendence wrote:
| Pedantically, I want to point out that first class
| functions predate the original iPhone by a large margin
| ...
| kaashif wrote:
| > records/pure immutable data classes
|
| Example?
|
| As far as I know, Java has final, which means that
| particular reference can't be re-assigned, but the object
| referred to remains mutable. You have to resort to e.g.
| having separate immutable and mutable interfaces or
| whatever to restrict a someone from mutating your object.
|
| If you want an immutable data class more than one level
| deep, I don't know if there's a convenient way to do that
| like there is with const in C++ (or the default behaviour
| in Rust).
|
| But I'm not a Java programmer, I haven't really kept up
| with the language. Happy to be proven wrong.
| gavinray wrote:
| JDK 17 record classes: record User(String
| name, Integer age, Boolean isActive) {}
|
| https://docs.oracle.com/en/java/javase/18/language/record
| s.h...
| dunefox wrote:
| This is destructuring but not pattern matching.
| gavinray wrote:
| How is this not pattern matching?
|
| In Scala, I would write: enum Expr:
| case INT(value: Int) case ADD(left: Expr, right:
| Expr) case MULT(left, Expr, right: Expr)
| def eval(e: Expr): Int = e match case INT(value)
| => value case ADD(l, r) => eval(l) + eval(r)
| case MULT(l, r) => eval(l) + eval(r)
|
| This "match" syntax is the example given in the Scala
| docs for Pattern Matching:
|
| https://docs.scala-lang.org/tour/pattern-matching.html
|
| The fact that Java happens to use "switch" instead of
| "match" is one of syntax, not semantics.
|
| JDK 17/18 introduces Sealed Types, which allow you to
| create ADT's sealed interface Expr {
| record INT(Integer value) implements Expr {}
| record ADD(Expr l, Expr r) implements Expr {} //
| etc }
|
| When you "switch" over sealed types, the switch
| expression is exhaustive if all members have branches and
| requires no default case + is typesound.
| oftenwrong wrote:
| Unfortunately, records are only guaranteed to be
| 'shallowly' immutable. It would be great if future Java
| versions provided a straightforward way to enforce
| immutability.
| throwawaymaths wrote:
| This is a matter of preference, I think. As a non-erlang
| practicioner I find Erlang to be far more readable than Java
| (which is good, because IMO Erlang authors have a habit of
| writing spaghetti code that's poorly organized). As a non-
| practicioner at some point in Java you run into annotations?
| Pragmas? and you stop being confident that your mental model of
| the code is correct. When I run into those I throw my hands up
| and start cursing.
| mdasen wrote:
| The JVM is pretty great. I could certainly nitpick things, but
| it's pretty great. Java is pretty decent. However, I would say
| that Java lost a lot of time and even now there are some decently
| rough edges.
|
| Java didn't evolve as a language for a while and that left the
| door open to other languages and other non-JVM ecosystems a lot.
| As the article notes, Java 8 was a breath of fresh air, but it
| was minimal in some ways. Lambdas and streams were great
| additions to the language. However, Java 8 came out in 2014.
| That's quite late to the game, in my opinion.
|
| C# is probably the closest competing language/ecosystem (albeit
| constrained to Microsoft for much of its life). In 2007 (7 years
| earlier) C# 3.0 had lambdas, the `var` keyword, properties,
| object initializers, the equivalent of streams (and really
| better), nullable types for value types (like int), etc. In some
| ways, Java has caught up - and C# lost a lot of time being
| constrained to the Microsoft ecosystem. However, in other ways it
| hasn't.
|
| _I just want a POJO_ : frankly, this has been a problem that
| Java hasn't solved and it's been well over a decade where
| everyone has known it's a problem. No, records don't solve it. In
| Kotlin, I can make a data class and it's easy. In Scala, I think
| they're case classes. In C# I have properties where I can say:
| `class Person { string Name { get; set; } }`. I can see that it's
| just a boring property without having to look at method bodies.
| If there's something special, that get or set can have a body to
| do stuff and it becomes really clear that it's something special.
| Getters and setters are a wonderful way to set traps for others
| on your team or for yourself a year later because you look at a
| class with 15 items and it's going to have 90 lines of
| getters/setters + another 30 lines of an empty line between each
| method. You look and just decide "yea, I'm sure this doesn't have
| special behavior" and go about your business just to get bitten
| later.
|
| _I want to be able to instantiate data easily_ : With Java, I
| can do `var person = new Person(); person.setName("Johnny");`,
| but that becomes pretty tedious and error-prone when
| instantiating a large object. With records you have a
| constructor, but then you're dealing with positional arguments
| and it's hard to understand. When reading the code, you don't
| necessarily know what each of the inputs means. Maybe your IDE
| puts the argument names in. When filling it out, I've found IDEs
| to only be somewhat helpful. With C#, I can do `new Person { }`
| and then hit the suggestion key combo inside the brackets in my
| IDE and it'll offer to fill out all the properties so that I get
| something like: new Person { Name =
| "", Age = 0, Address = "" }
|
| That means I don't forget about fields (as can happen if you're
| just doing `person.setX()` all the time). It's easy to see what
| is what when reading it. I can delete fields I don't want to
| initialize at the time. Yes, maybe immutable objects are the One
| True Way, but C# lets me choose (I can label properties with an
| initializer `init` rather than a setter `set` and then they're
| immutable).
|
| Kotlin offers stuff like this too because it's really useful
| toward creating code that's easy to create and maintain. Go also
| lets you initialize structs in a similar fashion.
|
| Java has come back to us a decade or more late with records.
| They're not bad, but they're only offering one thing. They don't
| cover what C#, Kotlin, Go, and other languages have offered for
| so long.
|
| The annoying thing about Java is that it doesn't feel pragmatic a
| lot of the time. It feels like the language hates stealing ideas
| from others. It's Java: people steal ideas from Java, not the
| other way around. People do crazy things just to get POJOs
| including Immutables (http://immutables.github.io), AutoValue
| (https://github.com/google/auto/), Lombok
| (https://projectlombok.org), Joda Beans
| (https://www.joda.org/joda-beans/), and maybe more. They generate
| lots of code at compile time or do funky runtime stuff.
|
| It just feels like Java misses the pragmatic stuff and still
| kinda doesn't want to handle that. I feel a bit silly harping on
| things like POJOs and setting data on a new object, but that's a
| big part of day-to-day stuff and it definitely pushes users away
| from Java towards languages that seem "better" simply because
| they don't have Java's oddly strong attachment to not offering
| simple value objects. Yes, again, records do something - but it
| feels like Java ignored how people are using Kotlin, Go, C#, and
| more and didn't go for something that would have been as widely
| applicable and pragmatic as it could have been.
|
| Java has a lot of great stuff like great GCs (yes), lots of cool
| research, great performance, and Project Loom is really exciting.
| I just wish the language would lean a little more practical.
| kaba0 wrote:
| The situation regarding POJOs are annoying, but I believe Java
| maintainers are fighting the good fight: introducing them in
| the language would hardcode this arguably bad pattern
| indefinitely. One might say that with the amount of code
| written this way, properties are already here to say, but I
| personally find Java's stance on feature addition much more
| sane than C# cool and quick, buy maybe too fast one.
|
| I like to believe that records with the upcoming 'withers' will
| be an adequate answer (if a bit too late) to this whole
| question.
| fabian2k wrote:
| I really like the C# object initializer syntax, and it looks
| like the next version might get rid of the last problem I had
| with it. Right now it does not play nice with nullable types,
| if a property is declared non-nullable you have to use a
| constructor or some ugly trick to circumvent the warnings. As
| far as I understand this will be fixed in .NET 7 (not sure if
| the decision is final, though) and you can get the full benefit
| of non-nullable types when using object initializer syntax.
|
| In general there has been quite some effort to allow a
| programming style in C# with less of the ceremony and verbosity
| that is often associated with C# and Java. And to me this does
| make working with C# more pleasant.
| diarrhea wrote:
| If you perhaps happen to know or have a pointer: how would
| that work in C#? A field not initialised will be null, and if
| it's non-nullable... what's its value going to be?
| fabian2k wrote:
| The check would be moved to the object initialization, so
| the compiler would tell you if you use the flexible object
| initialization syntax and left some non-nullable properties
| uninitialized.
| rr808 wrote:
| I've ditched Spring, am using Vert.x with Java 17, reactive &
| functional styles, records. Seems like a completely different
| language.
|
| If only project Loom will get out there so I wont be coding
| everything like Javascript I'd be happy. :)
| vips7L wrote:
| I'd rather write Spring than Vertx callback or observable hell.
| sabareesh wrote:
| Weird Spring is the reason why i am sticking to Java
| treis wrote:
| I just can't get past annotations as a thing. Seems like a
| crime against programming to me.
| sabareesh wrote:
| Well it is just another design pattern, i love annotations
| but it might be better even without it, Spring boot takes
| care of most of the things and it only needs very minimal
| annotation which makes sense.
| kaba0 wrote:
| I don't know, I think it's closer to some LISP magic macro
| than Lispers would like to admit. They are extremely
| powerful, and thus can be responsible for some very ugly
| code, but when used responsible, they are huge productivity
| wins.
| commandlinefan wrote:
| Spring would be my only reason to ditch Java.
| exabrial wrote:
| Try CDI! much cleaner, faster, and without the Factory
| Factory Factories.
| jayd16 wrote:
| Hmm Javascript has async though, no?
| 5e92cb50239222b wrote:
| That's exactly what was meant. With Loom Java will hopefully
| not have the same function split as languages like JavaScript
| (or C# for that matter) where you have to add lots of
| async/await everywhere; and instead will have something like
| Go (where everything is async).
|
| https://journal.stuffwithstuff.com/2015/02/01/what-color-
| is-...
| jayd16 wrote:
| I guess I was confused because right now you do not code
| Java like that.
| [deleted]
| vbezhenar wrote:
| Async stuff in JavaScript light years ahead of Java's
| Future madness. Loom might help but I'm not optimistic
| about it. For example Spring already kind of deprecated
| blocking http web client and new reactive WebClient is
| terrible. Will they create yet another BlockingWebClient?
| No they'll ask you to call `block` everywhere and write
| reactive nonsense filters if you need to enhance it.
|
| Spring is worst thing happened with Java.
| dymk wrote:
| That may be true, but JavaScript forces you to bisect
| your libraries (and functions) into Those that Understand
| Async and Those That Don't [0]. There appears to be no
| path forward if you want to avoid that.
|
| It's very difficult to write generic, reusable higher-
| order code that shouldn't care if it's doing a sync or
| async operation. Java at least is building a foundation
| in the right direction.
|
| [0] - https://journal.stuffwithstuff.com/2015/02/01/what-
| color-is-...
| vbezhenar wrote:
| If you mean that you can't write `map` which would work
| for sync and async functions with the same code, that's
| extremely rare problem IMO. If you really need that and
| don't want to write two versions of code, you can wrap
| blocking code with promises and use promise API from now
| on.
| dymk wrote:
| It's not at all a rare problem if you work in codebases
| involving async code. Many `Promise` APIs exist solely to
| work around that wart. Higher-order functions are the
| bread and butter of JS, and increasingly Java (especially
| modern Java).
| kaba0 wrote:
| But async stuff is a must in JS due to it being single-
| threaded (yeah I do know about webworkers).
|
| Just spawning a thread with a scope which will fork them
| at the end is just better from every conceivable way.
| Easier to grasp, easier to maintain, easier to debug -
| all of which are quite important when concurrency is at
| the table.
| [deleted]
| pca006132 wrote:
| I don't understand the part about go, does that mean go
| doesn't require async but gives you the functionality of
| async? (I never tried go)
|
| The problem with async is that we can separate when to
| start a task and when to ask for its result. The compiler
| can just add await everywhere an async function is called,
| it is trivial, but you don't get the flexibility of async.
| If everything is treated as async, you will need to await
| everything (perhaps some syntactic sugar to allow for
| immediate await)
| shellac wrote:
| > If everything is treated as async, you will need to
| await everything
|
| In go you work rather differently. You let tasks go off
| and do their thing, and provide a channel to communicate.
| Pulling a response from the channel is the 'await'. A
| good part of go's magic is that these tasks - goroutines
| - don't result in large amount of blocked threads.
|
| Java will soon have the building blocks of something
| rather similar to goroutines.
| pca006132 wrote:
| OK I see, but I think these two approaches address
| different problems? The approach used by go is more
| powerful than async but also more verbose. The
| implementation is also different, async can be
| implemented with a generator but goroutine can't.
| decebalus1 wrote:
| The time I used vert.x in my day job was by far the best Java
| experience in my career. Completely different language. And the
| vert.x maintainers have been all around great wrt to responding
| to issues and/or accepting contributions. Great framework. It
| has it's quirks and limitations but overall I absolutely loved
| working with it.
| johnklos wrote:
| ...and it's still a security nightmare...
|
| I think some developers took "write once, run anywhere" as a
| challenge, which is why I still have to keep virtual machines
| with ancient Java versions around to configure and use certain
| remote IP-based KVMs, certain IPMI functions, certain older fibre
| channel switches, certain poorly thought out IP cameras, and so
| on.
| nix23 wrote:
| Just wait until GO has so many years on the back, java is not a
| "security nightmare" developers/businesses with zero
| responsibility are.
| charcircuit wrote:
| Java has been very good at backwards compatibility for me
| except when they removed some unsupported internal classes from
| the 1.9 JDK, but there existed a workaround for still using it.
|
| I don't worry about security problems in the JDK or major
| libraries any more than anything else. I'm not sure where your
| security concerns are coming from.
| vips7L wrote:
| Why is that Java's fault? Isn't that the fault of the
| developers of your applications from not upgrading?
| nailer wrote:
| I might be wrong but I think they stopped working on major
| new versions for a decade. There seems to be Java 6 or 1.6 or
| whatever for a really long time. Like Netscape's version 4.
| kaba0 wrote:
| Who stopped what? Java 19 is the upcoming release.
| nailer wrote:
| Sun / Oracle stopped releasing new Java versions for a
| long time.
|
| I'm sure most people on HN are aware there are new
| versions of Java now.
|
| Edit: 'there seems' in my original comment should be
| 'there seemed' which may have caused confusion.
| nix23 wrote:
| Maybe Java 2 SE v1.4.2? It was like the JDK8 from the old
| days.
| Cwizard wrote:
| using the parent comments naming scheme it is actually
| 1.19, I don't know why they stopped developing major
| releases however.
| TheRealPomax wrote:
| But that is not the java naming scheme. Java stared using
| normal major version numbers back in the Java 5 days.
| They've developed major releases continuously for
| decades.
| babypuncher wrote:
| The real nightmare is Java's versioning scheme
| kasperni wrote:
| The version number increments by 1 every 6 months. What
| is so nightmarish about that?
| babypuncher wrote:
| To someone who has not written Java since High School in
| the '00s, I find the ecosystem a little confusing.
|
| My recent experience was this: I have a Windows box in my
| basement that hosts a Spigot Minecraft server for some
| friends and their kids. This box also hosts my UniFi
| controller software.
|
| The UniFi controller software requires Java 8, which is
| what Oracle offers for download on their website.
|
| Spigot usually requires the latest version, at the time I
| ran into this problem it was 17. You have to go out of
| your way and actually download the whole JDK for any Java
| version newer than 8.
|
| So I download and install JDK 17, which replaces the JRE
| 8 I already had running UniFi. Spigot works, and the
| UniFi controller appears to start up and function.
| However I quickly notice that the UniFi app is behaving
| erratically, and after some troubleshooting and googling,
| I learn that Java 17 is in fact _not_ backwards
| compatible with Java 8, so both of them need to be
| installed.
|
| Of course, Java doesn't make installing multiple versions
| side by side easy. It's doable, but even then they built
| no mechanism for a jar file to specify which runtime it
| needs and automatically run with it. So I had to write my
| own startup scripts for these apps calling the specific
| runtime they required.
|
| None of this was particularly onerous to figure out and
| deal with, but your average user is going to get stuck
| and feel frustrated. And it left a bit of a sour taste in
| my mouth because .NET has done a pretty good job of
| avoiding exactly these kinds of problems.
| kaba0 wrote:
| 1.6 and 1.8 and the like were major releases. While LTS
| doesn't have a well-defined meaning for OpenJDK, in
| general 11+6*n are the versions that are considered LTS
| (due to other vendors providing paid support for those).
|
| Let's not read more into arbitrary version numbers.
| ralmidani wrote:
| Java was actually not bad for me in class when learning software
| design and data structures, but soul-crushing to work with in the
| real world. Mindless, unnecessary use of getters/setters,
| interfaces, and AbstractFactoryImpls. Hiding almost every piece
| of functionality behind 10+ layers of indirection. Dependency
| Injection with Spring. They all make it feel like Java draws
| folks who actually __enjoy__ writing bloated, over-engineered
| garbage.
|
| YMMV, of course, and yes, there are modern frameworks other than
| Spring (Play is supposedly pleasant to work with), but life is
| too short to try to sort out that mess.
|
| I plan to stick to Elixir as much as I can, for as long as I can.
| When the language clicked for me, it was the biggest breath of
| fresh air since I decided to pursue programming as a profession,
| and even cooler than when I discovered Python/Django.
|
| Edit: obviously, Java is not all bad, and not all (or even most)
| people who use it fit the description above. But something about
| the ecosystem seems to draw those types (no pun intended)
| disproportionately.
| omegalulw wrote:
| What's your take on Kotlin? Neatly solves a ton of these
| issues.
| type0 wrote:
| Java is the perfect example of software "bureaucracy" for the
| sake of bureaucracy
| i386 wrote:
| All my new Java projects don't use spring for that very reason.
| Nothing wrong with the new keyword.
| geodel wrote:
| Excellent!. Its good to hear about places where Spring
| nincompoops do not shove their crap framework down everyone's
| throat.
| tomohawk wrote:
| Java has reached the status of Cobol - it is immortal because
| it is everywhere and has been around a long time.
|
| Because of that, there are a lot of Java devs.
|
| Our team works in Go, and so we get a few Java devs in once in
| a while as new positions open up. The biggest change for them
| is to get out of archonaut mode and stop overdesigning
| everything. After going through a 3-6 month cleanse, it's fun
| to see them complain about the legacy Java stuff and how overly
| complicated it is and how slow it is to build and test compared
| to Go.
| pwinnski wrote:
| I don't think this is an issue with Java, it's an issue with
| Spring. I'm baffled by the popularity of Spring.
| geodel wrote:
| But this article specially mentions Spring as some next
| generation rocket fuel to send Java even higher.
|
| The problem I see is as far Java ecosystem goes Spring is
| big, respected dev framework to be used liberally anywhere.
| So if a developer like me call Spring a revolting piece of
| shit software it is just me asking to become jobless.
| nick__m wrote:
| Old school xml based Spring is horrible and if that was your
| only exposure, I understand your aversion.
|
| But spring-boot has an almost zen like quality once you get
| that it favor convention over configuration. When I was a
| Java developer, I'd usually use spring-boot with the
| following dependencies to make the experience better:
|
| - lombok: to generate the boilerplate: constructors, getters,
| setters, equals, hashcode...
|
| - mybatis-spring-boot-starter: mybatis is a sql resultset
| mapper, you write the sql and it maps the results. I find
| that ORM like Hibernate or Eclipselink are a complexity trap:
| easy things are really easy but hard things are incredibly
| complicated, mybatis avoid that.
| ralmidani wrote:
| Sorry, but the popularity of tools which generate
| boilerplate for you is, in my opinion, one of the biggest
| indictments of the whole ecosystem.
| ledauphin wrote:
| agreed. every time I see static code generation I think
| "this is why people invent and use properly powerful
| languages".
| snewman wrote:
| I think it depends a lot on where you work and what sorts of
| projects you work on. I've been programming professionally in
| Java for the last 16 years and I have never encountered
| Spring. Nor do I typically see the stereotypical sort of
| FactoryFactoryManagerImpl complexity bloat. It is something
| you need to watch out for and steer clear of, in particular
| when selecting frameworks / libraries, but you can definitely
| live in the Java ecosystem without being pulled too far down
| this road. (The introduction of lambdas helped.)
|
| (Those 16 years are four years at Google, 10 years in a pair
| of startups, now 1.5 years at a medium-sized acquirer.)
| ralmidani wrote:
| I've seen similar patterns with tech that's older than Spring
| (Servlets/JSP). Also, wasn't it EJB that promoted getters and
| setters everywhere?
| nick__m wrote:
| JavaBeans in general promoted that convention. I first
| learned about Beans using Swing (the ui toolkit) since it
| makes heavy use of them.
| api wrote:
| The problem with Java is much more with the ecosystem than the
| language, for all the reasons you describe. Clean,
| straightforward software can be written in Java but it seldom
| is.
| butterNaN wrote:
| I have been learning Elixir for past couple of months. After a
| _long_ time, I am in love with programming+design again. It has
| honestly given my brain a much needed refresh.
|
| Of course, it can definitely be attributed, at least partly, to
| just moving to functional programming.
|
| Every day I look forward to 6'o clock, so I can stop working
| and continue on my own projects.
| afhammad wrote:
| You will also find Clojure just as refreshing / enlightening.
| My company uses Elixir but I've also done a lot of Clojure,
| give it a shot if you haven't.
| dopamean wrote:
| I spent almost all of my career writing Ruby before I ended up at
| a company that required me to write mostly Kotlin (a bit of scala
| here and there too). After a few years of Kotlin I don't want to
| use anything else. There's a bit more ceremony to getting things
| set up but the experience of writing Kotlin with Intellij IDEA
| has been so wonderful I'm happy to keep doing it.
| e67f70028a46fba wrote:
| The biggest thing Java is missing is full hot swap. Its been
| implemented via the dcevm but, inexplicably, has been ignored by
| both sun and oracle.
|
| This one, existing technology would make Java DX on par with the
| dynamic languages
| topspin wrote:
| > The biggest thing Java is missing is full hot swap
|
| The biggest thing missing in Java is an answer for the billion-
| dollar mistake. Real world Java is plagued by NPEs because a
| lot of Java is written by low caliber programmers. Java +
| functional error handling would be a monumental improvement.
| oftenwrong wrote:
| Java should adopt something like the Checker Framework
| Nullness Checker in its first-party tooling.
|
| https://github.com/typetools/checker-framework
| bhuber wrote:
| It doesn't fully solve the problem, but @lombok.NonNull helps
| a lot. It makes it clear which properties shouldn't be null,
| and catches NPEs closer to the source. Incidentally, lombok
| in general does wonders for boilerplate reduction.
|
| https://projectlombok.org/
| topspin wrote:
| > but @lombok.NonNull helps a lot
|
| Which @NonNull? There's
| javax.validation.constraints.NotNull,
| org.springframework.lang.NonNull,
| org.checkerframework.checker.nullness.qual.NonNull,
| org.jetbrains.annotations.NotNull,
| android.support.annotation.NonNull and a bunch of
| others[1]. The proliferation of Not|NonNull is evidence
| that I'm right, no matter how hard I get downed on HN.
|
| [1] https://stackoverflow.com/questions/35892063/which-
| nonnull-j...
| bhuber wrote:
| I didn't say it wasn't a problem - if I could wave a
| magic wand and get rid of the concept of null in Java I
| would. That isn't what we're discussing though - you
| said, "The biggest thing missing in Java is an answer for
| the billion-dollar mistake [- NPEs]". I've provided what
| I consider to be at least a partial answer. If you care
| about avoiding NPEs in Java, it's a pretty good solution.
|
| Realistically, null is so fundamental to the Java
| language that removing it would arguably result in a
| different language entirely. Certainly all existing java
| codebases would have to be refactored. The same goes for
| exceptions. That's obviously not an option when one of
| your primary selling points is backwards compatibility,
| so I'm not really sure what kind of solution you're
| looking for here.
|
| The answer to your SO link notwithstanding, I would argue
| the @lombok.NonNull is at least one of the best options,
| as it actually generates a null check that is executed at
| runtime. This makes it more powerful than most of the
| other solutions.
| topspin wrote:
| > Realistically, null is so fundamental to the Java
| language that removing it would...
|
| Again, as jayd16 pointed out a solution has been
| retrofitted to C#, Java's great nemesis. I don't accept
| the argument that this is somehow infeasible. Just make
| null assignments (including potential ones coming from
| libraries) an error and allow this feature to be scoped
| to your source files. Eventually the practice becomes
| ubiquitous. It's been done again and again in many
| languages and their various 'strict' modes.
|
| The only actual problem here is that Java language
| developers aren't feeling sufficient pressure to address
| it. They should, but they're not, and that's sad. That
| sort of sadness is a common theme with Java.
| kaba0 wrote:
| While this could be solved by introducing one into the
| standard lib, it is not that big of a problem in practice
| as nullability checkers understand all of these
| annotations.
| bberrry wrote:
| Kotlin solved that in a good way IMO. That alone makes it
| worth switching
| jayd16 wrote:
| You could always try C#. They have a non-null compile mode
| where variables are non-nullable by default. They did the
| work to mark up core libraries and also have some pragmatic
| handling of olde nullable calls in 3rd party libraries.
| commandlinefan wrote:
| > low caliber programmers
|
| Can't really blame Java for that, though - if everybody
| standardized on, say, Haskell (or whatever we might agree is
| the "gold standard" for programming), the low caliber
| programmers would find a way to do something stupid in it,
| too. The only way to get around low caliber programmers is to
| raise the standard, but any suggestion of raising (or even
| setting) a standard for programming invites accusations of
| "gatekeeping" (a gate that really, really, really ought to be
| kept).
| topspin wrote:
| > Can't really blame Java for that, though
|
| Hmm. Can't I? I know why Sun made Java. They wanted a
| platform to develop applications that didn't require the
| skill of a competent C++ programmer. They were targeting
| lower caliber coders.
|
| I'm a pragmatist; yes, Java programmers would still find
| escapes, but they'd do it less and so the net number of
| flaws would be smaller. As jayd16 points out, there is a
| pragmatic way to deal with this; provide a compiler mode
| that eliminates null dereferences and rework the standard
| library to accommodate this. Simple and obvious. Afterwards
| you can throw the switch on whatever code your facing and
| you'll know if you're dealing with crap or not.
| lenkite wrote:
| Enhanced hot swap using GraalVM has mostly caught up with
| capabilities https://www.graalvm.org/22.1/reference-
| manual/java-on-truffl...
| [deleted]
| bullen wrote:
| The only problem Java has is experienced C programmers don't
| build servers from scratch with it yet.
|
| Once they take that responsibility, the debate will be over
| because:
|
| "While I'm on the topic of concurrency I should mention my far
| too brief chat with Doug Lea. He commented that multi-threaded
| Java these days far outperforms C, due to the memory management
| and a garbage collector. If I recall correctly he said "only 12
| times faster than C means you haven't started optimizing"." -
| Martin Fowler https://martinfowler.com/bliki/OOPSLA2005.html
|
| "Many lock-free structures offer atomic-free read paths, notably
| concurrent containers in garbage collected languages, such as
| ConcurrentHashMap in Java. Languages without garbage collection
| have fewer straightforward options, mostly because safe memory
| reclamation is a hard problem..." - Travis Downs
| https://travisdowns.github.io/blog/2020/07/06/concurrency-co...
|
| "Inspired by the apparent success of Java's new memory model,
| many of the same people set out to define a similar memory model
| for C++, eventually adopted in C++11." -
| https://research.swtch.com/plmm
|
| This combined with the fact that Java doesn't crash and you can
| easily hot-deploy the classloader (maybe 100 lines) means nothing
| can compete that doesn't copy everything Java does VM + GC (hello
| C#, please don't downvote).
|
| To use anything else (than JavaSE without heavy deps.) on the
| server is madness.
| Banana699 wrote:
| Comparing Java with C is about as strawman-ny as it gets,
| you're literally picking on one of the oldest and dumbest
| languages in production usage. "The PDP-7 assembler that thinks
| itself a programming language", in the hilarious words of one
| wise guy.
|
| The problem Java experiences (not 'experienced') is that it
| isn't the 1990s anymore. People aren't easily hyped, not smart
| people at least. Programming language research, already way
| ahead of Java in 1995, moved far ahead some more. The internet
| and open source and free online education and social media
| means smart language designer(s) can now begin a baby project
| and put it on github and wait their luck for a corporation or
| organization that will support it, and they can wait a decade+
| on hobby mode till the luck comes. Java's competition isn't C,
| I highly doubt it ever was, it's dozens of far superior
| programming languages that were born after 1995, and some of
| those that were born before but weren't very populer because
| internet and open source barely existed in the 1990s and they
| weren't made by a corporation.
|
| Even if you keep overfitting the requirements function time and
| time again to gradually approach java (by adding "vast
| libraries" and "performance" to it, although neither of those
| things are specific to Java), you will eventually reach a very
| narrow niche with Java and Kotlin squarely in the middle, I
| know which one _I 'm_ going to choose if I'm willing to
| maintain my sanity and not drown in 'paper-work programming'
| that is the developing experience with Java. It's as easy as
| opening a source file in an IDE and naming it with a '.kt'
| extension rather than '.java', I'm in love with it.
|
| Companies use Java extensively ? So it's a COBOL then: Old,
| everywhere, infrastructure-critical, but an utter failure as a
| programming language in every way that is not "runs my old
| program I'm too afraid to re-write". This is forgivable in the
| case of COBOL because it's a literal proto-language, one of the
| earliest of the species. It's not forgivable in the case of a
| language designed when Smalltalk and ML and Haskell were
| around.
|
| The history of Java is the story of a corporation stumbling
| upon the idea of a VM (1960s stuff) and deciding that it's so
| good that they need something like this under their name right
| now, and not giving the slightest shit about the design of the
| language that sits on top of said VM. And they were right, the
| idea of a VM is really so fucking good that Java's aweful
| design was tolerated, until somebody relized running on the JVM
| no more means writing Java than running on x86 means writing
| x86 assembly, and wrote the first non-Java JVM language. And
| because VMs are so fucking beautiful, you get all Java code for
| free.
|
| >doesn't copy everything Java does VM + GC
|
| Come on, write those 2 words on any half-decent academic
| research repository and you will get hits from the fucking
| 1960s. Java is younger than Lisp, Smalltalk, Self, Haskell,
| Python and the same age as Ruby. All of those languages do VMs
| and GCs. Java's hotspot is taken from Self, that's documented
| stuff. And "Copying" isn't copying if it's a better
| implementation of the interface, JSON didn't "copy" XML, they
| reimplemented its interface better.
| nelsondev wrote:
| The p50 speed up from delaying memory management comes with a
| trade off, namely you get Garbage Collection pauses, bad p99,
| and spend your effort tuning the Garbage Collector instead of
| your code.
| philipkglass wrote:
| With Java 17 I found that using ZGC eliminated [1] the GC
| pauses that yield bad P99 latencies without any additional
| tuning. However, it has lower throughput than G1GC so your
| P50 advantages will diminish.
|
| [1] Reduced them to always well below 1 millisecond.
| cogman10 wrote:
| Which is always the tradeoff with GC. You get to pick
| latency or throughput and you trade one for the other.
| kaba0 wrote:
| In my experience, this is not related closely to GC and
| are apparent in many systems. A great book on
| optimizations explicitly mentions that "improving one
| aspect of performance may degrade another".
| plandis wrote:
| Low pause collectors exist explicitly for this purpose. ZGC
| and Shenandoah both trade throughput (more concurrent
| collections) for extremely low pause times:
| https://malloc.se/blog/zgc-jdk16
| nimrody wrote:
| Does that mean they also trade _memory_ for low pause
| times? Because, in our application, the memory required for
| avoiding significant GC pauses is at least 4x the amount of
| memory we actually need at any given time.
|
| This can be significant too.
| kaba0 wrote:
| Have you measured that with ZGC? Because due to using
| virtual pointers specifically, "third-party" tools may
| report higher virtual memory usage than what it actually
| uses.
| vbezhenar wrote:
| It's all about compromises. Only Rust is uncompromised.
| xxs wrote:
| > Garbage Collection pauses
|
| True concurrent GC have been available since late 2000s. Azul
| had a read-barrier GC as well - effectively a pauseless GC
| (or pauses under 1ms)
| xxpor wrote:
| An uncommon but not unheard method around that (in services
| that have diurnal patterns) is to throw memory at it and
| collect once a day during the down time. You can take the
| server out of service, restart it, and put it back in
| service.
| plandis wrote:
| This is kind of hard to do in practice unless you're really
| watching where you're allocating memory. It's very easy in
| Java to end up accidentally throwing a bunch of allocated
| memory on the heap without realizing it.
|
| Fwiw, the JVM now has a noop garbage collector so this is
| easy enough to benchmark.
| vbezhenar wrote:
| Can you provide an examples of accidentally allocating
| memory? The only example I'm aware of is autoboxing which
| is huge misfeature IMO.
| ska wrote:
| I read this was semi-standard memory management in the
| early lisp machine days, because that gc was so slow.
| bitwize wrote:
| Early Lisp (even pre-lispm) had no GC at all -- it just
| allocated until it ran out. Memory reclamation was done
| by saving the heap to tape and then reading it back --
| only live objects were saved. So it was kind of GC with
| extra steps; the first GC algorithms removed the steps.
| User23 wrote:
| To this day the Common Lisp standard doesn't require GC.
| kaba0 wrote:
| Does it really? With Java's G1GC the only knob you _may_ end
| up having to tune is the max target pause time - which pretty
| much chooses between better p50 and worse p99 va worse p50
| and better p90 - aka throughput vs latency, that are almost
| inherently opposite ends of the same spectrum. It is not GC-
| specific that any improvement will fail to increase one of
| those.
|
| So the actual tradeoff is more whether you want better
| throughput or tail-latency. To improve the latter, you have a
| singular command line option of using ZGC as well.
| hedora wrote:
| You mean the integer parameter "-XX:MaxGCPauseMillis"? The
| name says it all. You can do over a dozen sync disk writes
| in a millisecond these days.
| kaba0 wrote:
| Have you seen the output of JVM flight recorder or some
| other tool used to observe memory allocation/reclamation
| patterns? The JVM is _very_ lazy when it comes to GC -
| its algorithms are crazy good and can catch up with
| really high allocation rates as well. So the maximum
| pause time's unit doesn't really say much, and when it
| comes to dynamic memory allocation, the JVM is the best
| choice according to the biggest web services operating on
| terabyte sized heaps.
| titzer wrote:
| > tuning the Garbage Collector instead of your code.
|
| This is a feature, not a bug. Which is riskier?
| cogman10 wrote:
| Now-a-days, if you are tuning your GC you are almost
| certainly doing the wrong thing.
|
| While the JVM offers a plethora of levers to pull in case
| you are hyper concerned about different things, the
| heuristics are VERY good. Mucking with the fine grained
| details can disable heuristics and ultimately give you
| worse results than if you just left stuff alone.
|
| The levers to pull are algorithm, max memory, and max pause
| time. All other levers should be left alone unless you've
| got GC logs to back up what you think needs changing. (And
| even then... Do you really?)
|
| Typically, the better route is flight recorder and
| eliminating wasted allocations.
| mabbo wrote:
| That sounds a lot like the complaints about Java from a
| decade ago. Have you used it lately?
|
| Java's GCs are incredible and you have a menu of algorithmic
| options that let you avoid whatever problem you're worried
| about.
| jcelerier wrote:
| > Java's GCs are incredible and you have a menu of
| algorithmic options
|
| can these options be used in separate parts of a single app
| ? e.g. the app I'm developing in C++ has parts that do
| realtime audio, others that do GPU rendering, others that
| do classic Qt Widgets GUI, others that do offline
| computations on datasets - and they all have different
| performance characteristics and need different memory
| management schemes to get the best out of each, all while
| being in a single process; there's reference counting,
| tree-based allocation, pooled, linear, a GC-ish thing which
| ensure that memory is freed in specific non-realtime
| threads... Can that be done with Java or is one tied to a
| single GC implementation for a given execution of a
| process?
| imtringued wrote:
| If Java had isolated heaps then C++ would become
| redundant in every aspect except memory efficiency.
| marwis wrote:
| What are the advantages of isolates vs running multiple
| JVM processes other than avoiding slightly higher memory
| usage and some small context switch overhead on IPC -
| which should be negligent as presumably communication
| between isolated components would be coarse grained?
| dboreham wrote:
| The JVM GC is fundamentally the same as 10 years ago.
| bitcharmer wrote:
| Saying this just shows you don't know much about modern
| JVM.
| titzer wrote:
| Shenandoah did not exist 10 years ago, and G1 was not
| deployed.
| cogman10 wrote:
| 10 years ago the algorithms you could pick were serial,
| parallel, and CMS.
|
| Today we've removed CMS, added G1GC, and added ZGC.
|
| G1GC is similar to the parallel in the way it operates
| but is divided up enough to control for latency.
|
| ZGC is fundamentally different from the parallel
| collector or G1GC. Suggesting it is the same is to
| suggest you know nothing of the changes that have
| happened.
| kasperni wrote:
| With modern concurrent GCs such as ZGC [1] this is really not
| an issue for most people anymore.
|
| [1] https://inside.java/2022/05/30/sip053/#:~:text=ZGC%20was%
| 20d....
| lliamander wrote:
| Erlang is not as peformant as Java, but there are plenty of
| reasons to prefer the former to the latter:
|
| - a much better concurrency model, that gets you parallelism
| for free just by adding cores
|
| - no global gc pauses, low-latency
|
| - fantastic operational tools (trace debugging, remote shell,
| etc.)
|
| - Erlang/OTP gives you great middleware out of the box,
| including including queues, pub-sub, service monitoring,
| database, etc.
|
| - Honestly just a more expressive core language.
|
| All that said, I don't really have anything against Java. It is
| a great language for the server, but it is not the only choice.
| haspok wrote:
| All that said, Erlang is a very sharp knife, built for one
| specific purpose. This is just not true:
|
| "a much better concurrency model"
|
| If your program is CPU-bound, where real threads are king,
| then Erlang is a pretty poor solution. Because you cannot
| have real threads in Erlang, even if you wanted to. Number
| crunching or string processing are not its forte.
|
| Also, most enterprise software does not really benefit from
| green threads anyway, because the scale they are running on
| easily handles blocking JDBC and http request calls. Not all
| companies are google or want to run a telephone switch that
| handles >million concurrent calls...
|
| And finally, if you go Erlang, you get actors, whether you
| like them or not. You cannot have CSPs, for example, which in
| many ways are superior to actors. You don't get to choose
| your concurrency model, it is chosen for you. If your use-
| case suits this model, great. If not... not so much.
| lliamander wrote:
| There are responses to each of those points, but ultimately
| you are right that there are tradeoffs. My point was really
| that Java isn't the _only_ sane server-side language, and
| that Erlang is an entirely sane option.
|
| The one thing I will say is that, when I say Erlang has a
| better concurrency model, I mean that it is much easier to
| write correct concurrent code in Erlang than in Java.
| neeleshs wrote:
| Biggest benefit with Erlang for me is preemptive scheduling.
| Has a perf hit, but you don't get brownouts. Java lacks this
| and this results in hanging threads. A lot monitoring has to
| be there to detect these conditions . Project loom makes this
| somewhat better, but at its core, java threads are not
| preemptible
| imtringued wrote:
| Java uses regular OS threads that provide preemption by
| default... Whatever you are talking about has nothing to do
| with preemption.
| neeleshs wrote:
| Right. I meant interruption is cooperative.
|
| https://docs.oracle.com/javase/tutorial/essential/concurr
| enc...
| bullen wrote:
| No Erlang can't share memory between cores atomically.
|
| Erlang can only scale 1-to-1 things like phone calls.
|
| Java is the ONLY language that scales many-to-many with
| stable non-blocking IO and concurrent parallelism that shares
| memory atomically AND doesn't crash.
| TheRealDunkirk wrote:
| And for the fraction of the software projects out there
| that that actually need this feature as a hard requirement,
| I'm sure it's wonderful.
| pdimitar wrote:
| Yeah, all web apps everywhere are definitely a fraction,
| I'm sure. :P
|
| Green threads are an amazing fit for web apps. I made a
| career out of using those for web apps and API apps.
| bullen wrote:
| Well many-to-many IS the point of the internet.
|
| Think MMO here, which is the "metaverse" thing they keep
| talking about.
|
| Simulating 3D reality over the network IS the ONLY thing
| humans can do now that doesn't HAVE to burn all the
| energy we got left while giving use a tool to experiment
| without risk.
|
| So I'm building the final 3D action MMO game engine.
| imtringued wrote:
| Everyone dreams of their own MMO but nobody wants to pay
| for it except whales.
| bjourne wrote:
| Imo Erlang's scalability benefits are oversold. Unless you're
| a national carrier the performance of Java far outweighs
| Erlang's scalability. Instead, Erlang's undersold killer
| feature is its robust support for hot code reloading. It
| enables almost any part of the system to be upgraded without
| affecting running processes. Other languages and VMs can't do
| that because they optimize call frames differently and rely
| on mutable state. It's like building a new road on top of an
| existing one without impacting traffic. Almost magic and very
| important for always on services like emergency numbers.
| lliamander wrote:
| Yep, I would say that it's support for ops in general is
| it's biggest strength (deploys, monitoring, fault
| tolerance, etc.)
| kelnos wrote:
| I feel like Erlang somewhat missed its timing window on
| this, though. With platforms like AWS, GCP, and Azure, you
| don't really worry about upgrade downtimes, because you
| just roll out a new fleet of servers (or new fleet of pods,
| if you're using something like Kubernetes), and then drain
| the traffic from and decommission the old fleet.
|
| Certainly there are a lot of companies managing real
| physical servers, where this is not as feasible, but I
| think the ease of server provisioning makes hot code
| reloading just not that important to most engineering
| teams.
|
| (And personally I'd be wary of using something like that,
| considering that the rollback path -- in that case that you
| deploy bad code and need to back it out -- sounds not as
| robust.)
| lliamander wrote:
| I work in an AWS/K8s-heavy shop, and it is pretty great,
| but we have a fairly sizeable engineering team.
|
| Managing K8s microservices is easily an order of
| magnitude more work than managing them in Erlang as
| applications.
| exabrial wrote:
| > no global gc pauses, low-latency
|
| Java also has this for at least a few years now. G1GC and ZGC
| in JDK17 offer no global stops unless absolutely necessary,
| and ZGC even has latency targets.
| MaxBarraclough wrote:
| Also Shenandoah. Those Java garbage-collection folks have
| been busy recently.
|
| Or is it that people interested in doing ground-breaking
| garbage collection research tend to target Java?
| the8472 wrote:
| > - no global gc pauses, low-latency
|
| ZGC has sub-millisecond pauses https://malloc.se/blog/zgc-
| jdk16 And afaik azul's C4 collector has no global pauses,
| only per-thread pauses (which are also short)
| pkolaczk wrote:
| Low pauses, low memory overhead, low CPU overhead. In Java
| world, pick one. In C/C++/Rust/Zig you can have all three
| at once.
| krzyk wrote:
| Add memory safety to the list. And allow to select only
| 3.
| pkolaczk wrote:
| But that's not performance category. And, btw, Rust has
| all 4 of them. If we're talking about safety guarantees
| then let's add data race freedom to the mix. Or use-
| after-free protection for non-memory resources. ;)
|
| Java is cool language and has many nice features, but its
| type system is not its major advantage.
| stiray wrote:
| https://go.dev
|
| Experienced C developers have switched to it. Actually it gets
| even better, they are extremely productive in it. Don't trust
| me, check github.
|
| I wonder why. /s
| BenoitP wrote:
| With Loom incoming, Go's only unfair advantage (shared with
| Erlang) may be gone soon. I guess we'll have the answer in a
| few years.
|
| Will the next WhatsApp be written in Java?
| lliamander wrote:
| It will take more than green threads to be equivalent to
| Erlang. Erlang's concurrency model depends upon a
| completely non-shared memory model, which Java will never
| have.
|
| Edit: and programming it in Java will always be more
| laborious than in Erlang. Sure, you could put Erlang on the
| JVM (as the Loom folks want to do) but then is Java really
| the winner here, or did Oracle just make an alternative
| BEAM?
| BenoitP wrote:
| Surely having a shared memory model increases the design
| space? Or is this about memory management performance?
|
| A benchmark should settle things in that case. Maybe it
| will be a draw! Erlang's almost-no-op deallocation vs
| Java's world-class JIT. Some applications are bound to be
| better suited to one specific side. I guess we'll see;
| but it cannot be denied that with Loom Java started to
| compete on a non-void part of Erlang's land.
| cogman10 wrote:
| It's certainly a trade off. One thing erlang can do which
| java cannot is survive one of it's actors OOMEing. That
| kills the actor and not the VM.
|
| That comes at some extreme costs and implications to what
| the VM is capable of achieving, but it is something
| that's pretty impressive.
| lliamander wrote:
| Absolutely. And I'm not particularly partisan in this: I
| like Erlang ( the language in general as well as the
| concurrency model) and if Java moves closer to that then
| all the better.
| wewtyflakes wrote:
| While interesting, I'm not sure how that will translate
| into practice. How easy is it to hire up an organization
| of Erlang developers, versus, Java developers? I suspect
| Java's features as compared to Erlang will be good
| enough, that the specific use-cases enabled by
| knowledgeable Erlang developers will be non-competitive
| in the general developer labor market, but I am open to
| being wrong/educated.
| haspok wrote:
| Loom does a small fraction of what the Erlang VM is capable
| of doing.
|
| For one, the Erlang VM has built-in preemptive green thread
| scheduling, which means it can suspend your green thread at
| ANY instruction, not just when an IO call is in progress.
|
| Loom is a step in the right direction, but Erlang is in its
| own universe for what it was designed for.
| throwawaymaths wrote:
| Erlang still has failure domains as a first class concept
| which neither go or Java are likely to have ever.
| BenoitP wrote:
| > which means it can suspend your green thread at ANY
| instruction
|
| True. Out of curiosity: what's the use case for this?
|
| Surely side-effects-out-of-your-system is enough?
| notamy wrote:
| > True. Out of curiosity: what's the use case for this?
|
| Scheduling is deterministic, which is a VERY useful
| property to have. See ex.
| http://erlang.org/pipermail/erlang-
| questions/2006-December/0... about changing scheduler
| determinism.
| marwis wrote:
| The thread you linked is about the benefits of inducing
| scheduling non-determinism.
| slekker wrote:
| Is Loom THAT big of a deal? Can you point me towards some
| references of why this is the case?
| SureshG wrote:
| Yes, IMO game changing for java. Read this JEP -
| https://openjdk.org/jeps/425
|
| Here is a simple echo server running on Virtual thread
| (using same old blocking APIs, handle 5m persistent
| connections) - https://github.com/ebarlas/project-
| loom-c5m/blob/main/src/ma...
| nocman wrote:
| > To use anything else (than JavaSE without heavy deps.) on the
| server is madness.
|
| That's a terribly broad generalization. There are multiple
| other options that are entirely sane.
| DoesntMatter22 wrote:
| When all you have is a hammer... What a ridiculous take, most
| server apps don't use Java and they are just fine.
| bullen wrote:
| This was true until 2017 when I became a C programmer.
|
| They are fine until they need to scale and iterate quickly
| without downtime.
| DoesntMatter22 wrote:
| Java apps have plenty of downtime during deploys, that
| isn't uncommon at all. You have such a naive view of
| java.
| Scarbutt wrote:
| What other good dynamic runtimes with widespread use like the
| JVM exist?
| TrueDuality wrote:
| Restricting your world view to only programming languages
| with dynamic runtime environments like the JVM is a major
| handicap.
| [deleted]
| hedora wrote:
| Linux, for C/C++/Rust.
|
| It also provides memory safety and multiprocessor support.
| lliamander wrote:
| BEAM
| sushisource wrote:
| > This combined with the fact that Java doesn't crash
|
| Huh? Doesn't crash in what way vs. C? I can still deref a null
| pointer and blow up.
|
| Java's perfectly fine, and I have no idea why you'd write C any
| more, but if you care about (extreme) performance and not
| crashing, Rust seems the obvious modern choice here.
| plainnoodles wrote:
| One of the weird things about Java is that there's a big low-
| latency/high-performance Java community around that stems
| from Island (now owned by NASDAQ) using Java as the
| platform/language for their matching engine. Then, talent
| flow from that team resulted in lots of proprietary trading
| shops using Java to low-latency trading/order execution.
| SlipperySlope wrote:
| kaba0 wrote:
| If you do that in C, your program may run "just fine" on the
| surface forever, yet it can silently corrupt all of its data.
| Java _can_ catch NPEs and handle them appropriately (e.g. a
| web server might just _answer_ server error 500, but it will
| continue to run with well-defined semantics). I don't think
| the two is comparable. Even Rust will go off the happy path
| with a single use of unsafe, and there is no sailing back
| from there, while a Java program can't crash in a UB-like
| way.
| vbezhenar wrote:
| Dereferencing null is undefined behaviour in C. Probably it
| could be handled with platform-specific code, but handling it
| correctly not the easiest thing to do. Other than
| dereferencing null, there're so many ways to accidentally
| blow up C code and something like reading uninitialised
| memory is truly undefined behaviour which can't be worked
| around.
|
| Java does not have undefined behaviour at all. Dereferencing
| null would throw NPE which is ordinary exception, completely
| fine to handle or suppress or whatever. There's no concept of
| uninitialised memory. The only sources of undefined behaviour
| in Java is calling native code or using unsafe methods which
| are very rare and usually located in well tested library
| code.
|
| Even stack overflowing is defined behaviour and you can
| easily recover from it.
| tomohawk wrote:
| I've never seen Java code in production handle NPEs, OOMs
| or other such conditions well.
|
| It's a shame Java does not have value types, which makes
| nulls a much rarer thing to have to deal with.
| mcculley wrote:
| I have worked on big projects with up to ~100 developers. On
| the C projects, someone's null-pointer dereference brings
| down the whole process. On the Java projects, the event
| handler or daemon thread has an exception handler at the top
| that logs the error and keeps executing. This is a huge
| difference in behavior.
|
| Sometimes, you want to fail fast and be forced to fix that
| bug. More often, I want to keep doing whatever I can to test
| and develop the system and find more bugs without restarting
| the whole thing.
| pkolaczk wrote:
| You can have a null pointer handler in C as well.
|
| But this is generally not a good idea. I find software that
| does not crash early and visibly but instead tries
| continuing despite an obvious bug very brittle and often
| causing trouble because it can take a long time before
| operators notice the problem. If you accumulate enough bugs
| of this type, you get a mess that "kinda works" but is full
| of surprises.
| mcculley wrote:
| Yeah, I implemented an "atcrash" handler as a library
| which I embedded into multiple projects. But it was only
| so I could walk the stack, dump a stack trace into the
| terminal, and tell the user, "Please email this to the
| developer." And then as cleanly as possible shut down the
| process. In C, as you say, not much else can be safely
| done.
| pkolaczk wrote:
| In Java if you encountered a null pointer exception or
| out of bounds error at the global level, there is also no
| guarantee you can safely continue, and dumping the stack
| and terminating is the only sensible option. Sure, the
| JVM is ok, but your app state might be already corrupt.
| mcculley wrote:
| This has not been my experience at all.
|
| The JVM is not corrupted by a NPE or out of bounds access
| unless you are using native code.
|
| For example, I worked on a large X-Windows/Motif
| application with many developers. If some library
| dereferences a null pointer, it is game over. Kill the
| app. In a Java Swing app we built for a similar use case,
| we just trap the exception in the AWT event dispatcher,
| log it, and keep going. Yes, sometimes an exception has
| ruined the global state in some catastrophic way, but
| this is rare. We can keep running and debugging without
| restarting the whole app.
|
| Another example is a web app: Any exception that bubbles
| up to the main request handler loop is likely (in our
| architecture) to happen before any change is made to the
| persistent store. Log it and handle another request. This
| makes debugging a lot easier than restarting the whole
| app.
| LaGrange wrote:
| > This has not been my experience at all.
|
| This has been my experience with software written in Java
| by developers who think it was not their experience.
|
| > In a Java Swing app we built for a similar use case
|
| ...oh no. I actually tend to associate Swing UI with
| weird, undefined behaviors, and whenever I'd look under
| the hood, it would nearly _always_ be due to them trying
| to swallow runtime exceptions. Pure hubris, as far as I'm
| concerned.
|
| > Another example is a web app: Any exception that
| bubbles up to the main request handler loop is likely (in
| our architecture) to happen before any change is made to
| the persistent store. Log it and handle another request.
|
| Please, please, _PLEASE_ just crash the server. The OS
| will handle it, it will be OK, and systemd will even do
| the right thing and give up if your thing crashes
| _persistently_, including all the fancy stuff like
| keeping track of how often it crashes.
|
| I've done too much cleaning up after overly-confident
| superstar architects, your examples just brings painful
| memories. I beg you stop trying to be clever and just log
| the error and crash the app.
| pkolaczk wrote:
| I haven't said that the JVM would be corrupt by NPE. But
| C program state would also not be, and you could do the
| same handling as in Java.
|
| But if your code invoked an NPE or bounds check, then it
| means either the algorithm is incorrect or the data it
| processes are already corrupt by incorrect processing
| earlier. Continuing in such situation increases the risk,
| because you don't have any guarantees which parts of the
| application state might have been already corrupted by
| the bug. I've seen many many times an NPE was a result of
| a shared data corruption caused by a data race. JVM does
| not guarantee thread state isolation, so one bug can
| break the state of all threads.
|
| > Log it and handle another request
|
| That gives you only a false sense of safety. A Java app
| (and any other app) may die for many other reasons you
| can't handle. You need to be prepared for that anyway if
| you want a reliable service. But if you are prepared for
| that, and your server can restart in 0.1 second, you
| don't win anything by recovering from NPEs.
| kaba0 wrote:
| Depends whether your "null pointer" is truly zero, or
| some random value that was not initialized.
| tomohawk wrote:
| No doubt, Java GC is a feat of engineering. But it has to be to
| avoid being swamped by the lack of mechanical sympathy between
| the language and memory management. Pretty much everything you
| do generates lots of unnecessary litter, which then must be
| eventually collected.
|
| Except in very narrow circumstances, I've not ever seen Java
| perform at the level of C or C++, especially when I/O is
| involved. Java typically needs 2-4x the memory and a lot more
| cores to do the same job. That's fine if you bought the machine
| and the machine is big enough, but if you're leasing an EC2,
| why pay more every hour?
|
| These days, my C, C++, and Java days are behind me. We do
| mostly Go, and couldn't be happier. The GC and language have
| really good mechanical sympathy, and the bad memories of tuning
| Java GC are fading. We pay a small tax in terms of CPU and
| memory over using C, but not remotely like what we saw with
| Java. And yes, we built prototypes of critical use cases in C
| just to see how 'bad' Go would be, and were very pleasantly
| surprised that Go compared very well indeed.
| a-dub wrote:
| there have been a handful of infrastructure projects in java:
| kafka and cassandra come to mind immediately, but there are
| certainly others.
|
| i think what has always sort of steered me away has been a few
| things:
|
| 1) i've long been interested in snappy, interactive and
| realtime local and server things. and the jvm can do this
| stuff, but usually it's better suited for server side use where
| it can be warmed up appropriately. this may also just be a
| personal dogma that i need to get over.
|
| 2) every language and runtime has its quirks where you have to
| breakdown the illusions of the language itself and understand
| the internals to get the best performance, but i feel like java
| is the worst instance of this, where the tricks that people go
| through in order to control the gc seem excessive.
|
| 3) i like simple and concise programs where i feel like the
| java ecosystem encourages code sprawl. hello world has so much
| weird stuff and a serious java project has thousands of small
| source files where computer aided programming (ie. a proper
| java ide) is not really optional. i find this not only to be
| unergonomic, but also challenging for being able to quickly
| understand what a foreign codebase is doing in a short
| timeframe. maybe it's different from the perspective of a
| primary developer on one of these large projects though (and
| possibly quite pleasant).
|
| 4) for some reason, i've always liked feeling closer to the
| metal. even scripting languages "feel" closer because of the
| jvm abstraction. this is probably also a personal dogma.
|
| > He commented that multi-threaded Java these days far
| outperforms C, due to the memory management and a garbage
| collector.
|
| people who like java say these sorts of things all the time. i
| haven't seen a head to head comparison that confirms it though.
| (although i have not looked). regardless my understanding is
| that once a jvm is warmed up, it can be quite performant-- and
| that it has opportunities for live optimization that you don't
| get in a classic c/c++ runtime.
|
| i don't think c/c++ will be going away as long as operating
| systems are still written in c. a java operating system
| seems... strange to me. but that said, i think java has proven
| itself in terms of high performance application server
| software.
| pca006132 wrote:
| But what kind of C program is he comparing against? Single
| threaded ones? Not heavily optimized ones? Optimized concurrent
| C programs that use locks rather than lock-free data
| structures? Or heavily optmized C programs with lock-free data
| structure? It is unclear to me.
|
| Also, wondering how much of that overhead in the C program is
| due to malloc (can be overcome by memory arena)
| quadcore wrote:
| _The only problem Java has is experienced C programmers don 't
| build servers from scratch with it yet._
|
| Please explain. What kind of crazy jack write servers in C?
| (Real question, trying to learn here)
| varjag wrote:
| Servers written in C is the status quo here in real world.
| cozzyd wrote:
| The developers of apache httpd, nginx, postgresql, redis,
| among many others?
| xxs wrote:
| you really dont need redis if you have java. I see zero
| reasons to offload my datastructures via TCP, instead of
| have them locally. If need be, replicated them.
| vasilakisfil wrote:
| Usually you need redis to scale up horizontally, meaning
| with multiple servers/processes, and still keep
| consistency in your data. In general redis is a very
| useful tool that provides various features, even pub sub.
| otabdeveloper4 wrote:
| I assure you that people writing C++ on the server know how to
| use lockfree structures and optimized allocators. Using
| something with a garbage collector when you have access to all
| that is madness.
| badpun wrote:
| Java does not (yet) have green threads, which limits the number
| of connections you can serve per machine. You can go to Scala
| though (it has them) and still stay on the JVM.
| kentonv wrote:
| Oh, please.
|
| I once worked on a Java-based server at Google that had to
| answer requests with millisecond latency. In order to achieve
| this, the server had to block garbage collection most of the
| time. Periodically, each instance of the server would ask the
| load balancers to stop sending requests to it, so that it could
| then safely run the garbage collector, and then ask for traffic
| to return.
|
| We likely would not have used Java had we foreseen needing to
| do this. I believe some time after I left, it was all rewritten
| in C++.
|
| Sadly the garbage collection debate is full of people who
| _want_ GC to be the answer to everything, and have chosen their
| arguments and beliefs through confirmation bias to support
| their desire. Many of these "GC is faster!" arguments come
| from that, but it just ain't true most of the time. Performant
| GC is incredibly complex and incredibly complex systems tend to
| fall over if you don't use them in exactly the right way.
|
| Worse, GC is extremely bad at managing resources other than
| local memory. In complex distributed systems or other software
| that manages external resources, GC languages tend to be ill-
| equipped for the job because they lack explicit resource-
| management tools like RAII. In Java, you sometimes see
| frameworks where everything has a `dispose()` method and
| complex systems are built to make sure that `dispose()` method
| gets called... this is a failure, it should be handled by
| destructors.
|
| GC is generally nice and convenient for application
| engineering, but a poor fit for systems engineering. The
| boundaries between the two are admittedly fuzzy.
| discreteevent wrote:
| > requests with millisecond latency
|
| You're getting into hard real time territory there. That's a
| different universe and will require special considerations
| even in C. I think it's fair enough for people to discuss
| server performance and assume that the context is our normal
| programming universe.
| kentonv wrote:
| Of course! There are plenty of use cases, including server
| use cases, where Java is a great choice.
|
| But I was reacting to bullen's assertion that "To use
| anything else on the server is madness.", and to the rather
| exaggerated performance claims.
| ransom1538 wrote:
| Google should have picked a real language: php. When script
| is completed all resources are freed, let the OS figure it
| out. No manual GC drama.
| MaxBarraclough wrote:
| That's a strategy called _arena allocation_ or _region-
| based memory-management_ , and it doesn't have to be tied
| to the lifetime of a process or interpreter.
|
| There's nothing special about PHP, which if I understand
| correctly uses reference-counting with conventional garbage
| collection to handle reference cycles. As I understand it
| this strategy is non-competitive in all performance
| metrics, compared against modern garbage collectors.
| luciusdomitius wrote:
| Speaking of this, have you of LMAX Disruptor[0]? You probably
| have. And yeah, having fine control over the memory
| allocation and garbage collection in such a high-level
| language (multi-platform vm!) is akin to building a ship in a
| bottle. However, in which stack creating multi-level
| distributed stock exchange with sub-milisecond response times
| is easy?
|
| 0. https://lmax-exchange.github.io/disruptor/
| kelnos wrote:
| > _I once worked on a Java-based server at Google that had to
| answer requests with millisecond latency._
|
| That's... not really normal, though, and sounds like the
| exception that proves the rule. For the vast majority of
| applications, Java will perform better, be easier to develop,
| and be safer to run, than an equivalent server written in C
| or C++.
|
| At my previous job we used to run realtime audio through a
| Java server (RTP streaming). I do remember in the Java 6 days
| that the GC would need tuning to ensure that GC pauses
| wouldn't delay audio to the degree that there would be
| dropouts or perceptual delays. But with Java 8 (and later
| releases), which came with better GC implementations, those
| problems just went away. Sure, realtime audio is usually fine
| with even up to 100ms pauses (or even 200ms, sometimes) -- so
| this is much more tolerant than your sub-ms example -- but we
| rarely saw anything even remotely that long with the more
| modern JVM GC implementations, without really having to tune
| behavior that much, or at all. Meanwhile, P99 stats for most
| JVM services were in the low to mid tens of milliseconds, and
| anything longer was always due to calling out to external
| services, like relational DBs.
|
| For the rare case like Google's, sure, it's absolutely
| expected and appropriate to need to use a non-GC'd language
| instead, at least for some things. For pretty much _anyone_
| else, the JVM is more than adequate, or can be made adequate
| with some reasonably simple GC tuning.
|
| > _Many of these "GC is faster!" arguments come from that,
| but it just ain't true most of the time._
|
| I don't agree. I think it _is_ true most of the time. But I
| think many people don 't think about what they mean by
| "faster". Faster as in throughput? Sure, a modern,
| performance-oriented GC (like the JVM's) can very easily beat
| manual memory management there. Latency? Well, ok, that can
| be a bit harder, so you need to evaluate things on a case by
| case basis, and possibly do some GC tuning to get the
| latencies you need. But even then, you can usually do just as
| well (or better) on the latency axis as well. Just not
| always. But I don't subscribe to the "But sometimes..."
| school of objections. Yes, sometimes some technologies don't
| work for certain use cases. That's fine. Choose your
| technology wisely. But in Java's case, it really is just
| "sometimes". Not most of the time.
|
| Let me reiterate, though: Google is not the common case! By a
| long shot! It is an outlier, and it's expected that a company
| like Google will have to deviate from the mainstream to reach
| its performance targets sometimes. But also consider that
| (from what I understand) even Google has a _ton_ of services
| written in Java, and they... work just fine, no?
|
| > _In complex distributed systems or other software that
| manages external resources, GC languages tend to be ill-
| equipped for the job because they lack explicit resource-
| management tools like RAII._
|
| Eh. I initially thought of this as a problem, but in
| practice, I've rarely run into an issue with this sort of
| thing. Maybe it's because there's still vestiges of the C
| programmer in me that will always think about memory
| ownership and lifecycle, even when writing in a GC'd
| language, but I've rarely had my own issues (or seen issues
| written by others) where someone has forgotten a `.close()`
| or `.dispose()` on something. The "try with resources" syntax
| can help here too, even though IMO it can be kinda
| cumbersome.
|
| And as much as the Java docs tell you to essentially never
| override `finalize()`, it can be a useful "last ditch" tool
| to ensure that any "manual dispose" owned references get
| cleaned up, and you can also add logging there; I'll often do
| something like "Got to finalize() without disposing of Foo
| instances: BUG!". I also appreciate when third-party authors
| who write `dispose()` methods also do this. It's not perfect
| by any means, but IMO the convenience of relying on garbage
| collector rather than manual memory management far outweighs
| this downside.
|
| Lately I've been writing a lot of Rust, and I'm enjoying the
| sort of "middle ground" approach, where I don't have to think
| about memory management as much, but don't have to worry
| about GC performance, either. Certainly Rust doesn't
| eliminate these concerns; I still need to think about
| ownership and object lifetimes, but it's never "oh crap, I
| forgot to free() something and there's a memory leak", or "oh
| crap, I tried to use something after free()ing it and
| crashed", it's more like "ugh, rustc doesn't agree with me
| that this object lives long enough and refuses to compile
| it". Annoying, but I'd rather find this out at compile-time
| than runtime.
|
| But then I'll go back to writing Java or Scala after being in
| a Rust project for a while, and remember how nice it is to
| just not have to think about these things.
|
| > _...but a poor fit for systems engineering._
|
| Absolutely agreed. But I would not call writing distributed
| network servers "systems engineering", even though I do agree
| that the boundary between systems and applications
| engineering is indeed fuzzy.
| kentonv wrote:
| > But I would not call writing distributed network servers
| "systems engineering",
|
| I would agree that a web application server is usually
| application engineering even if you are running 1000
| replicas of it. I would not write these in C++. (Well
| that's a lie, I probably would but I would admit it was a
| terrible idea.)
|
| On the other hand, the container engine that orchestrates
| the web app server is systems engineering, as is the
| database it talks to for storage.
| galdosdi wrote:
| > I once worked on a Java-based server at Google
|
| This is kind of a fair comment, but kind of not, because Java
| performance and GC internals have really advanced a lot in
| the last decade. It would really help if you qualified
| approximately when this was.
|
| > Sadly the garbage collection debate is full of people who
| want GC to be the answer to everything
|
| Good point. I think more recently, the Java world is very
| aware of this. Native and off heap memory has been getting
| more use in performance sensitive stuff for quite a while.
| You can totally just (essentially) malloc and free in Java,
| if you really need to for performance.
|
| That said, if you want to be able to make your code
| accessible to a wider audience, GC is a must. There are tons
| of junior and midlevel developers who don't really have
| experience working with non-GC application code (and in many
| cases are intimidated by it!), and you will be restricted
| from hiring any of them if you use a non-GC language.
|
| If that's ok, then that's ok, but with Java you can still do
| a little off heap stuff in the critical part you need to,
| encapsulate it behind a safe API, while letting the juniors
| run amok in the rest of the codebase.
| [deleted]
| kentonv wrote:
| I agree with all this. Java is a great application
| programming language.
|
| But bullen was arguing that Java is the best for servers of
| all types, which is what I object to.
| chopin wrote:
| Afaik, a malloc is not guaranteed to return fast. With those
| requirements it's hard even in C.
| oaiey wrote:
| Funny how the revival of Java is similar to the revival of .NET.
| After some stale years, both languages refined themselves and are
| back in the top competition (.NET in the VM space, Java in the
| language space).
|
| It really shows which languages can re-invent themselves (Java,
| .NET, PHP, ..) while some fail (Fortran, Basic, Pascal, Perl,
| ..). Not sure where JS is ;). Python seems to have survived the
| 2/3 schism by now.
| diarrhea wrote:
| I guess both JavaScript and Python reinvented themselves
| through gradual typing. It makes Python quite a different
| language and JavaScript literally a different language.
|
| My most recent small (1k LoC) Python project is "fully typed"
| and therefore practically type safe (not strictly speaking
| though). Lots of the large libraries are typed as well, which
| is important.
|
| For Python, work around the GIL might be the next evolutionary
| step, that time in the name of performance.
| oaiey wrote:
| I agree. It seems like the road for dynamic languages goes
| through optional typing. And it is logical because their weak
| spot right now are huge systems.
|
| I have to add that JavaScript would greatly benefit from a
| solid base class library
| otabdeveloper4 wrote:
| W-w-wait, I thought all software as unequivocally being written
| in Rust now?
| jmartrican wrote:
| I was doing live coding in an interview yesterday and the
| interviewer said "you have a problem in your code, you put var,
| and this is Java". I had to explain that the language has
| modernized quite a bit.
| abledon wrote:
| For anyone else who can't get the LLCoolJ popup player to work
| while reading the article:
| https://www.youtube.com/watch?v=vimZj8HW0Kg
| falcolas wrote:
| Java's adequate. It's like a Toyota Corolla (insert your boring
| car of choice here if you don't feel this one works for the
| analogy). Not the prettiest, not the fastest, not the most
| efficient. But it gets you from point A to point B with little
| fuss or muss. I totally get why companies adopt and standardize
| on it.
|
| Do I use it for personal projects? Nope. Because it's not fun to
| "drive". For that, I pick the equivalent of a Mazda Miata (insert
| exciting car of choice), which for me is usually a Lisp.
| hedora wrote:
| I'm going to go with "Java is like a 2006 Chrysler 300". I'm
| basing this on this list of the most popular fleet vehicles in
| the US:
|
| https://www.fuelexpress.net/blog/just-for-fun/4597-2/
|
| The Corolla is known for reliability and fuel economy. It's the
| car you'd buy for your fleet so you could ignore it, and then
| you would ignore it, and some day, people would start assuming
| you are going out of business or something because all your
| fleet vehicles are from the late 90s.
|
| On the other hand, the 300 claims to be those things, but has
| terrible fuel economy, and apparently likes to unexpectedly
| spin out. They claim that new ESP magically fixes the problem,
| even though they've been claiming such things for years. It's
| actually supposed to be a luxury car or something, but
| apparently for some reason it is used as a fleet vehicle, where
| it is a poor fit.
|
| Also, since it is a Chrysler, I assume it is unreliable. Oh
| look, I'm right:
|
| https://cars.usnews.com/cars-trucks/chrysler/300/2011/reliab...
|
| (In fairness, the newer ones are supposedly reliable. Sort of
| like how Java is supposedly pause free now.)
|
| Filling out the rest of the analogy:
|
| fuel economy => Java startup costs, and asymptotic / constant
| factor slow downs because it doesn't support zero cost
| abstraction.
|
| spinning out => The GC, of course
|
| magic ESP => The next GC solves the pause / thrashing issues
| (promised every year since at least 1998)
|
| reliability => Constant API churn, the 8 => 11 => 17 => 20
| treadmill, and (of course) log4j.
|
| targeting luxury segment => Java targeting toasters, IoT and
| web browsers back in the 90s, but only being able to run on
| hilariously overbuilt and power hungry enterprise boxes
| instead. Also, the classloader's open world assumption.
| Ologn wrote:
| > targeting luxury segment => Java targeting toasters, IoT
| and web browsers back in the 90s, but only being able to run
| on hilariously overbuilt and power hungry enterprise boxes
| instead. Also, the classloader's open world assumption.
|
| There are over three billion active Android devices in the
| world, since 2014 they have been running Android Runtime
| runtime environment, which uses Java (or Kotlin) bytecode.
| Before 2014 Android used Dalvik, which did the same thing.
| This is running on some pretty low powered devices.
| hedora wrote:
| Fair point. I forgot about Android, though it's an (almost)
| completely different code base.
| kaba0 wrote:
| I have very vague knowledge of cars, but I know for a fact
| that your characterization of Java is just bad, no matter how
| good you car analogy-creation may be.
|
| I won't even correct the others, but how come Java is
| unreliable? Like, I have a hard time thinking of _anything_
| in the category of computer programs that would fair better.
| hedora wrote:
| Have you ever had to maintain an old enterprisey Java
| thing? It's pure hell.
|
| Basic dependencies (like JUnit) break API compatibility
| every few years, and then they stop distributing the old
| version for new JVMs, so you're forced to port your code.
| The GC falls over in production at the least convenient
| times. People somehow decide everything should be stringly-
| typed, and that the best choice between .properties, xml
| and JSON is "all of the above, and also this in-house DSL".
| There's this common pattern called "vendoring" where you
| load multiple incompatible versions of the same library
| into the same JVM, and exploit loopholes in classloader
| semantics to prevent it from noticing, and ungracefully
| exiting (which is what it really, really should do).
|
| There's no way to use language improvements and static
| analysis to improve program semantics over time (like there
| is in, say C++) because none of the language level
| abstractions are sound.
|
| For example, you have a line like "static Foo foo = new
| Foo()". Guess what? foo can be null sometimes. Here's an
| unrelated problem: Think you have a function that doesn't
| throw exceptions? Nope. Some third party garbage can throw
| errors during normal operation instead. Think that
| eliminating down casts in your program means it won't throw
| ClassCastException on unexpected lines? That hasn't been
| true since generics were invented. Think Optional gets rid
| of null pointer exceptions? Nope. Instead, it's actually a
| tri-value null. After all, you can always create null
| references to an Optional (and, looping back to the
| beginning of the paragraph, you can't avoid creating null
| references to Optionals in idiomatic code!)
|
| I could go on for hours.
| kaba0 wrote:
| > Have you ever had to maintain an old enterprisey thing?
| It's pure hell.
|
| FTFY. And yes, I have worked on old Java apps, they are
| not worse than any other app that lived for a similarly
| long timeframe (and the fact that there seem to be more
| old monstrosity in Java may just mean that it actually
| manages to do its work written in java, and not fail in
| some other language).
|
| Why don't you have a bin repo for old junit versions?
| Nonetheless, not updating is just technical debt that
| will have to be paid once either way. Regarding GC, it
| was never as bad as its name in my opinion, but it
| improved dramatically in recent years. If it fails it is
| more than likely a programmer error (which is very easy
| to debug thanks to the JVM's killer observability).
|
| Regarding XML and .properties, this is related to
| _enterprisyness_ not java, nor the JVM. These are
| meaningful abstractions to a degree but are overdone
| badly more often than not. Vendoring is not really a
| hack, it is a correct choice from the JVM's PoV (in
| short, a canonical name and a classloader pair is unique
| inside the JVM), but it can be abused, and application
| servers kind of do so indeed.
|
| Wtf, Java has probably the best tools when it comes to
| static analysis. It actually has a well-defined
| specification of what has to happen under nigh every
| circumstance, and Java is huge in academy as well so
| different kind of analysis is an active research topic,
| especially that Java is also huge in the industry.
|
| Runtime exceptions are a thing everywhere, I again fail
| to see how are they relevant here, and Java is completely
| type safe with generics, your statement regarding that is
| completely false. If you don't have casts in your
| program, it can't fail with classcastexception
| (reflection-hackery aside).
|
| Optionals are a mistake but the only fault lies in those
| who put a null inside.
| ElectricalUnion wrote:
| > Optionals are a mistake but the only fault lies in
| those who put a null inside.
|
| If you, or a third-party exposed a "Optional", then it's
| the API mistake. You're never supposed to expose an
| Optional as either input or output; they're clunky
| implementation details of the Java Maybe monad.
| kasperni wrote:
| > Optionals are a mistake but the only fault lies in
| those who put a null inside.
|
| You can't. 'null' represents an empty optional.
| adrian_b wrote:
| I am not convinced that Java is adequate.
|
| I do not know if the problems are related to the Java language
| or to the typical Java programmers, but Java is the only
| programming language where I have seen a strong correlation
| between the programming language used to implement some
| application and a low quality of that application.
|
| During decades of experience with various programs, whenever I
| was surprised that a program seemed to be abnormally slow, or
| it had an unusually ugly GUI, or it had a GUI that was
| impossible to customize, e.g. it was impossible to change the
| default font or the size of the font, or it had various other
| annoying features seldom encountered in other programs, I
| discovered that it was written in Java.
|
| Most of these annoying programs where commercial programs, some
| of them very expensive programs.
|
| The most recent Java problem that I have encountered was last
| year, when I could not install some expensive program, because
| the installer crashed immediately.
|
| After some time wasted to discover the reason, the conclusion
| was that the installer was written in Java and it always
| crashed immediately on any computer to which a 30-bit monitor
| was connected.
|
| That program had both Windows and Linux versions, but both
| crashed in the presence of a 30-bit monitor, so the Java
| installer was of the kind "write once, crash anywhere".
|
| The workaround was to disable the GUI of the installer and make
| an installation from the command line.
|
| There are some 15 years since I use only 30-bit monitors, but
| this was the first time when I have seen such a behavior
| (probably because I avoid Java programs, due to past
| experiences). Googling has shown that this was actually a well
| known bug in Java installers, which had not been solved in a
| long time.
| valbaca wrote:
| I'm with you, even as a Java developer I can immediately
| recognize when something was written in Java: it's ugly and
| slow. When it crashes, you know they missed a NPE or tried to
| use multiple threads.
| gorjusborg wrote:
| > I'm with you, even as a Java developer I can immediately
| recognize when something was written in Java
|
| Sure, if we are talking about desktop applications and we
| ignore the exceptions (Intellij / Minecraft).
| 3836293648 wrote:
| Minecraft's menus absolutely have that hacky terribleness
| feeling. It's still much better than Minecraft Bedrock
| (the C++ reimplementation), but it's also noticeably
| behind everything else
| haspok wrote:
| Java UI and applets have been abandoned long ago (>10 years).
| This was partly due to webapps becoming the standard, but
| also the realization that for desktop apps non-native UIs
| just suck.
|
| The vast majority of Java (=running on the JVM) software
| these days is server-side, without any user interface.
| TheRealDunkirk wrote:
| Precisely, and exactly why the programming world is an
| absolute, cargo-culting mess of Javascript frameworks and
| libraries these days. Sure, React is winning the mindshare
| war now, but it's just the least ugly baby winning the
| beauty pageant at the county fair.
| adrian_b wrote:
| You are right that all the Java programs with which I had
| problems were programs with a Java GUI.
|
| With Java programs without a Java GUI, I never had
| problems.
| tannhaeuser wrote:
| What seems to be little known is that Java began life as a
| language for programming set-top boxes with lots of UI, and
| continues to be used for Blue-Ray disc menus/apps. Sun and
| Oracle also invested quite a bit into developing JavaFX as
| an attempt at "RIAs" running in browsers when it was clear
| Applets were going nowhere, yet JavaScript wasn't quite as
| developed as it is today, and Flash wasn't seen as a choice
| for complex apps.
| bityard wrote:
| > Java is the only programming language where I have seen a
| strong correlation between the programming language used to
| implement some application and a low quality of that
| application.
|
| Funny, I hear this sentiment more about PHP which deserved
| its poor reputation in the early days but is actually quite a
| nice language now and has been for a good long bit.
|
| I think the biggest problem some people have with certain
| programming languages is that they don't "look" a certain way
| they prefer (syntax-wise), or don't have enough modern
| buzzwords associated with them.
| halfmatthalfcat wrote:
| What does that make Scala? A RAV4?
| speed_spread wrote:
| Scala is a ring of four Corollas welded by the edges of their
| rooftops so that rolling over only changes the set of wheels
| you're using. Also, all wheels are omni directional so you
| can drive sideways when required.
| gclaramunt wrote:
| Lexus
| yurodivuie wrote:
| Still a Corolla, with left-hand drive and manual
| transmission.
| btmcnellis wrote:
| A Pontiac Aztek.
| falcolas wrote:
| I'm going to catch hell for this, I just know it.
|
| A Chrysler PT Cruiser. Odd looking, beloved by its fans, and
| a reasonably adequate (if quirky) to drive.
| kaba0 wrote:
| I don't know, probably some truck would be a better analog. It
| ain't sexy, but it was made to be a blue collar language, and
| it is the one that ships cargo nigh everywhere.
| mgomez wrote:
| You're not alone as someone else made a similar observation
| in a previous thread[1]:
|
| > To me Java is like a garbage truck. You get to work, start
| it up, do a nearly invisible but absolutely essential duty,
| then, at the end of the day, you turn it off and go home. No
| one dreams about garbage trucks or puts one in a car show but
| they're there and ready to go right back to work when you
| are.
|
| [1] https://news.ycombinator.com/item?id=26834177
| perardi wrote:
| To really nitpick the analogy: Java is a Ford Transit cargo
| van.
|
| It's primarily used by enterprise shops. You'd never brag you
| about driving a van. It's not fashionable. It's kinda ugly.
|
| But...it gets the job done.
| topaz0 wrote:
| Speak for yourself. I brag about driving a 2013 transit
| connect.
| throwawaymaths wrote:
| Corollas don't come with all sorts of weird (now aging)
| buzzword-driven preferences like nudging you towards xml,
| factories, etc.
| falcolas wrote:
| Personal rant: I've never understood the hate towards XML.
| It's a practical and flexible markup language that does not
| depend on whitespace or quoting every bloody thing. Plus,
| every markup language invented since has had to re-invent XML
| things that, surprise surprise were actually needed. Paths,
| schemas, comments, etc.
|
| I get frustrated with JSON because of things I could do in
| XML that I can't do in JSON without breaking the spec. And
| that doesn't even cover how annoyingly verbose anything done
| in JSON is.
|
| Anyways.
| no_wizard wrote:
| The bottom line, from my experience is this:
|
| XML means you have to think about how you're architect
| information exchange much more thoughtfully, because XML is
| much more strict and follows very explicit rules. It also
| means you have to develop a schema for your interchange.
|
| With JSON, you can, more or less, just serialize as is, not
| much thought in the world, and it can be understood by the
| client. You're not obligated by the protocol to do anything
| about developing a schema or anything of that nature.
|
| Yes, parts of the XML world have now bled over (defined
| schema and path algorithms being the big ones I think) but
| they're optional for better or worse.
|
| Everyone takes the path of least resistance when given the
| opportunity at the end of the day. This is _especially_
| true of software engineers I 've found.
| gmfawcett wrote:
| Eh, not really. You have the option of defining schemas,
| of course, but it's not required.
|
| In practice, I think most of us used XML the same way
| that people use JSON today: here's some data from my app,
| figure out how to pull out the bits you need. No high
| ceremony required.
| cptskippy wrote:
| Java/.NET have first class support for XML and SOAP, most
| other languages don't. It's too easy to use XML in those
| languages. Other languages don't have that tooling or
| support and it's just a slog.
| acdha wrote:
| It's very similar to Java: there's a not bad language
| buried under huge layers of bad practice and design by
| committee which most people are stuck using, with a side
| serving of market failure around the developer experience
| (e.g. Maven, Spring on the Java side, tools being built on
| the orphaned libxml meaning that you're stuck in the early
| 2000s level of XPath, etc. in many cases).
|
| XML 1.0 was decent but I soured on most of the "standards"
| based on it after too many iterations of chasing through a
| chain of specs pulled in by reference where you had to read
| a bunch of ponderous W3C documents and non-working examples
| to learn that the spec authors hadn't correctly modeled the
| problem, nobody had time to work on any of this, and the
| only extent implementations either weren't compatible or
| had a lot of tedious workaround code. Bonus points if they
| were replacing a legacy format and ended up with a result
| which still required deep familiarity with the original
| format but was also much less efficient.
|
| These problems are cultural. JSON certainly isn't immune to
| this but the Java/XML world has more people who felt the
| need to LARP as Very Serious Architects designing extremely
| expensive systems. Things like Atom show grownups can use
| XML, too, but they're notably the exception.
|
| In Java, the most direct counterparts I see are the places
| where people felt like they should copy the Sun library
| developers for code which is far less universally used and
| took on a huge support cost building abstractions and
| customization points which were largely unused, often only
| for security exploits.
| wvenable wrote:
| In Java-land, XML became a replacement for actual code. And
| for that, it's kind of terrible.
|
| But programs that store their data as XML rather than some
| proprietary binary or text format are awesome.
| vips7L wrote:
| I've never written XML in Java in the past 7 years of
| being a developer.
| wvenable wrote:
| It's not the way Java is done now because, as noted, it
| was awful. Java is almost 30 years old now. Developers
| who worked in Java 20 years ago had a pretty different
| experience than it is now.
|
| However, I'm sure a lot of that code still exists.
| Consultant32452 wrote:
| [Cries in spring config]
| pwinnski wrote:
| In Spring-land, I think you mean.
|
| I enjoy Java. I do not enjoy Spring.
| brazzy wrote:
| Using XML became optional in Spring as soon as Java got
| annotations.
|
| Which was in Java 5.
|
| 18 years ago.
| [deleted]
| tannhaeuser wrote:
| I think Spring, Maven (and ant before), JSP, and J2EE
| descriptors gave XML a bad name, as fields of application
| where a _markup_ language wasn 't adequate. XML was meant
| as a simplification of SGML to formalize and extend HTML on
| the web, but was overhyped as serialization format for
| everything and anything for all the wrong reasons, among
| them that XML sold well to management.
|
| It can be argued that, despite not a primary use case for
| markup, XML has found a useful niche in b2b service
| payloads and government, banking, and health services in
| particular. The use case for those might have been "web
| services" in the original sense where simple CSS-like
| transforms and styles are applied to payloads for display
| in browsers, but the JSON community hasn't brought forward
| a serious replacement for XML Schema, so XML payloads
| kindof keep sticking around in long-term projects.
| dwaite wrote:
| Formats are designed for a purpose.
|
| XML was built for a very limited set of purposes - to
| create a common base markup for various document formats.
| It was almost purpose-built to create something like XHTML
| - a mixed content system where you can do semantic
| decoration of textual media content, and extend it with
| things like SVG and MathML.
|
| The problem is that it was _not_ built as a cross-platform
| data structure interchange format, but it wound up being
| used for that way more than its intended purpose. This was
| partially because of the extensibility story - companies
| could agree on a common base format, and define their own
| extensions to add additional data. However this was a pain
| - the XML tooling was often generic to support both kinds
| of usage, and the language itself was ambiguous because the
| expectation that the underlying document being described
| would have document-specific clarifications on use and
| tooling.
|
| JSON is an object notation - it is a way to transmit
| hierarchal data. It has limited extensibility in the sense
| that you can define rules for data processing, such as
| 'ignore things you don't understand' or 'name things which
| are not agreed upon with URI rather than short names'.
|
| Trying to use JSON to represent the content model of HTML
| will just cause pain, because thats not what it was built
| for. It isn't even re-inventing things from XML, it is just
| cramming a square peg in a round hole.
|
| Neither format was built to be a configuration file format
| for users to hand-edit config. As a result, they suffer
| limitations in their syntax and features (closing elements
| in XML, quoted property names and lack of comments in JSON
| being the most commonly cited). TOML is one popular choice
| for this sort of use case.
| silvestrov wrote:
| xml also scales much better with deeply nested documents
| (such as html documents).
|
| A deeply nested JSON document is difficult to navigate in.
| Even with prettyprint it is counting indentation to find
| out what kind of info this level has.
|
| Take the html page for news.ycombinator.com and convert the
| html document into JSON format. It becomes unreadable.
| winstonewert wrote:
| > that does not depend on whitespace
|
| This is precisely one of my complaints against XML, it does
| depend on whitespace. In JSON, I know that any excess
| formatting whitespace can safely be removed. But excess
| formatting whitespace is part of the document in XML and I
| can't know in general whether it can be safely removed or
| not.
| lliamander wrote:
| Once upon a time I was deeply in the world of XML Schema,
| XSLT, and XQuery. It was actually pretty cool.
|
| But using complex, poorly specified, possibly Turing-
| complete "config" files written in a markup language that
| isn't the primary language your app is written in is a
| serious code smell.
|
| It means you would either be better off using an embedded
| scripting language (like Groovy) or a better core language.
| aeze wrote:
| You consider JSON to be more verbose than XML? I'm curious
| to hear why.
| gen220 wrote:
| I think people dislike XML precisely because it's so
| flexible and unopinionated. It means that when you're
| parsing a new XML source, you have to look for data that
| might be encoded in two or three little niches. God help
| you if it's encoded in each of them, and if the data
| therein is contradictory. Basically, it's easy to "hold it
| wrong" in a way that harms consumers.
| lenkite wrote:
| A schema can be written in 15-30 mins to make XML as
| opinionated as you want it to be.
| adgjlsfhk1 wrote:
| and then you'll read an xml file that doesn't meet your
| schema and your code will crash
| lenkite wrote:
| With nice validation errors pointing to line, col where
| unexpected information was found. I'll definitely take
| that.
| falcolas wrote:
| > I think people dislike XML precisely because it's so
| flexible and unopinionated.
|
| You're probably right.
|
| > Basically, it's easy to "hold it wrong" in a way that
| harms consumers.
|
| I feel a bit like this could equally apply to things like
| GraphQL. I spend more time reading the docs on how
| someone's internal data model is built than I do writing
| GraphQL queries. And if I get that data model slightly
| wrong, my query's garbage.
|
| But that's probably a separate, vendor specific
| (coughnewrelic), rant.
| solarkraft wrote:
| Over-engineering (relative to the complexity of the task
| you want to solve).
|
| Enterprise solutions are often so complex and generic
| that they can theoretically do and interoperate with
| anything, but are also hard to get started with and use
| well.
|
| People like to start with simple things and expand from
| there instead of buying a whole house when they just want
| a sink (am I using the phrase right?). In my opinion this
| makes a lot of because it avoids unnecessary complexity
| and sensitizes people to why some complexity is in fact
| necessary.
| gen220 wrote:
| Every "contract" language (e.g. .graphql) I've used so
| far has it's ups and downs.
|
| One that keeps biting us in GQL, for instance, is that it
| won't let you define a union type for mutation inputs, so
| you end up needing N methods like `GetByX(X)`,
| `GetByY(Y)`, `...` instead of a single `Get(X|Y|...)`.
| Not to mention support for versioning message types,
| etc...
|
| FWIW: I think proto3 is probably the best I've used, at
| length and in production. Granted it has its "warts", but
| the idioms to circumvent them are fairly well-documented
| and agreed upon, even if they're a bit "ugly" in the
| syntactical sense.
|
| FWIW pt 2: Like yourself, I think, I would not consider
| JSON to be appropriate as a schema-defining "contract"
| language in 2022, for a company that plans to be around
| in 5 years. There are too many better options available.
| mind-blight wrote:
| I think it also got horribly abused by some use cases.
| People tried to allow programming in it (e.g. if
| statements and loops) when an actual DSL would have been
| a better solution.
|
| I know that was my last straw before I started assuming
| that anything that required XML would be painful to work
| with. It wasn't an entirely fair assumption, but it was
| correct often enough that I used it as a helpful
| heuristic.
| AnimalMuppet wrote:
| You're comparing XML and JSON, and you're complaining about
| how verbose _JSON_ is? Um, JSON is, like, _half_ as verbose
| as XML is.
| jayd16 wrote:
| You should update your perspective.
| jeroenhd wrote:
| My problem with Java is that C# exists which does huge portions
| of the stuff Java excels at just... better.
|
| Before, .NET only ran on Windows which disqualified it from
| many serious applications server deployments. Today, this is no
| longer the case for everything but cross platform GUI
| libraries, and even those are an option if you're okay with not
| having Linux support.
|
| It's more akin to the old car you had just before you bought
| your Corolla. It was also pretty decent, but it was starting to
| have issues.
|
| The JVM ecosystem is quite expansive and it's capable of
| running many things that would be a pain to develop in house
| (or pay a third party developer for). However, Java isn't the
| only popular JVM language anymore and you're no longer forced
| to use Java to interact with its surrounding ecosystem.
|
| The language and the ecosystem around it aren't going to go
| away for at least a decade, but I think it'll slowly move the
| way of COBOL and FORTRAN: perfectly good languages, with
| perfectly good situations they outperform their competitors in,
| practically exclusively used for niche use cases and legacy
| software systems.
| thankful69 wrote:
| C# is not a better Java by any means, Java has a more diverse
| and greater ecosystem, you have plenty of choice for tooling,
| IDEs, libraries, platforms, etc... With C# you are pretty
| much stuck with Microsoft which everyone knows what that
| means (.net core runs everywhere, but still attached to msft
| in many ways), if you are serious about the C# ecosystem, you
| need to use Windows, C# IDEs outside of visual studio are
| mediocre at best. If you like running a operating system that
| doesn't give a f** about your privacy and developing for that
| platform then sure. There is a reason why C# (even with Msft
| huge lobbying efforts, not only to the goverments but to dev
| communities) have been relegated to boring(and sometimes
| dying) industries which get huge discounts for using Azure.
|
| EDIT: typos
| solarkraft wrote:
| I agree with most of your points, but also really dislike
| Visual Studio. Rider has very good compatibility (unless
| you care about the constant hangs and crashes and buggy,
| nonsensically laid out eye sore UI and dumb defaults and
| ...) and VSCode (the one with all the proprietary Microsoft
| stuff) is quite usable. What kind of blew me away was
| finding out that they support Jupyter notebooks now.
|
| The Visual Studio team seems to dislike dotnet supporting
| other platforms, but it's one of the most critical things
| for its survival. The more the VS team hates it, the more
| likely it's to be the right choice (probably a good rule of
| thumb for building IDEs too).
| dijit wrote:
| Jetbrains rider is not mediocre by any stretch and many C#
| developers prefer it, even on windows, even though it's
| paid.
| pron wrote:
| > but I think it'll slowly move the way of COBOL and FORTRAN
|
| That could be true of any language that's achieved great
| popularity, but in 2022 Java is the language that dominates
| server-side development (by plurality, not majority), it is a
| technological leader in areas of compilation, garbage
| collection, and low-overhead in-production profiling, no
| other single language looks posed to seriously challenges
| Java's dominant position on the server (as PHP seemed for a
| while), and, at 27, it is more popular than COBOL was in its
| (rather short) heyday.
|
| But it is true that Java is among a select set of languages
| (alongside Python, JavaScript, and C) that have managed to
| achieve a level of success sufficient to become "a COBOL" or
| "a Fortran" someday.
| bcrosby95 wrote:
| What stuff does C# objectively do better than Java?
| babypuncher wrote:
| Benchmarks generally show C# outperforming Java, but not to
| a degree that most people would worry about. Performance-
| sensitive applications are still going to go for something
| native.
|
| One of C#'s biggest assets is Anders Hejlsberg of Turbo
| Pascal fame. He's been in charge of C# since its inception.
| He's done a very good job of keeping the language clean and
| concise, and generally ahead of Java when it comes to
| adopting features like generics and functional programming.
| runevault wrote:
| I thought Anders was full time on Typescript these days?
| Certainly his fingerprints are all over c# from being in
| charge for a long time though.
| babypuncher wrote:
| He still acts as the lead architect on C#, in addition to
| working as the core developer on TypeScript.
| tejinderss wrote:
| Nope, Mads Torgersen is lead architect on c# nowadays,
| Anders is 100% on Typescript's typechecker.
| kaba0 wrote:
| I would put it differently: C# has a higher performance
| ceiling due to it having access to lower level controls
| (mostly value types), but for idiomatic code, there
| really is no such difference (and if there is any, I
| would say it goes towards Java). Also, for programs
| having very dynamic allocation patterns, Java's GCs are
| the state-of-the-art and are basically impossible to
| beat.
| the_only_law wrote:
| > Performance-sensitive applications are still going to
| go for something native.
|
| What's up with Java in HFT stuff then? I've never
| understood this: from what I understand in order for it
| to work, you have to intentionally avoid doing many
| allocations, and that seems like you'll be throwing
| massive amounts of the ecosystem (Javas biggest strength)
| away.
| solarkraft wrote:
| Can't really be objective here. You could also argument
| this makes it worse, but it gives you to take shortcuts for
| things Java would make very hard or cumbersome (unsafe
| code, properties).
| titzer wrote:
| Generics, LINQ, structs, delegates, to name just four.
| hhjinks wrote:
| Can you explain _why_ you think C# does those things
| better than Java? And what they correspond to in Java?
| babypuncher wrote:
| C# is like Java except your team can churn out new features
| 30% faster.
|
| At least that is my experience running the only .NET team at
| a company that primarily runs Java.
| pwinnski wrote:
| It's hard to see how C# will ever find wide usage outside of
| the MS ecosystem. It's so intrinsically tried to MS.
| lenkite wrote:
| > My problem with Java is that C# exists which does huge
| portions of the stuff Java excels at just... better.
|
| Might want to give some evidence of this. Also, C# has no
| plans of green threads. It went the async/await way which is
| a pain.
| akra wrote:
| I don't feel its the biggest pain to be honest, at least
| not in the .NET world where the Async API is so persuasive.
| I don't think the paradigm would suit Java - the API
| changes to make it ubiquitous would make it take too long
| to add value. People seem to code with it (the Async
| workflow) just fine, and it's a decent model to write some
| async algorithms. For example firing a few in parallel,
| starting a task but leaving it running and awaiting it
| later, etc. The advantage for me is that there is some
| overhead with Async dispatch - the abstraction of
| coroutines, green threads, etc is cheap but isn't free and
| maybe seeing where it could prop up isn't always a bad
| thing. There is value in knowing that an operation could be
| async, at least in my time programming and it has a cost
| that you may not want to pay, defer, delegate to someone
| else, etc especially in hot loops (e.g. IO).
|
| As a single anecdote working in both languages in my
| current job in a cross platform environment when having to
| write Java it feels just that bit more painful, and just
| that bit harder to get the same performance for the class
| of apps I write. YMMV.
| baldfat wrote:
| I personally use Racket (Lispish) just because it is so much
| fun to build whatever I want and customize it. It just feels
| good to have my small projects just fit me perfectly.
| skybrian wrote:
| I wouldn't use Java again because I am done dealing with the
| brokenness of Maven and Gradle. They are the opposite of
| "little fuss and muss." The Go build tools fit your analogy
| better.
| SureshG wrote:
| > The Go build tools fit your analogy better.
|
| Go uses two build tools for any non-trivial projects. One
| write in go.mod and another in Make :D (see this - https://gi
| thub.com/kubernetes/kubernetes/tree/master/build/r...)
| NoSorryCannot wrote:
| Whoever invented the car analogy should pay for what they did.
| [deleted]
| jgust wrote:
| Bagging on car analogies is like driving a Hellcat, it's not
| practical.
| [deleted]
| dls2016 wrote:
| I remember an intermediate OO class in Java 20 years ago...
| the existence of the El Camino was proof of the terribleness
| of both multiple inheritance and car analogies.
| mindslight wrote:
| Indeed. All cars suffer the same speed limits and traffic, so
| how effective your car is ultimately depends on how you drive
| within those constraints. The analogy slyly condenses
| everything down to some car-manufacturer-marketing version of
| "fun", betraying both spirited drivers and whatever topic it
| is applied to.
|
| Since we're throwing out analogies, Java-the-language is more
| like a riding lawnmower. It is capable of getting you to your
| destination, but will be slow and painful the entire time.
| There is probably some external constraint that you'll be
| forced to endure this, like losing your license.
| shagie wrote:
| This was something / part of the plot of The First $20
| Million Is Always the Hardest. I recall the main character
| getting a car (turned out to be rented) that was really
| fast and taking the team out driving on 101 in rush hour
| traffic to make this point.
| mgkimsal wrote:
| I think the car analogy is just extending a base analogy.
| There could be other siblings. Perhaps AnimalAnalogy could
| extend BaseAnalogy and we could talk about animals instead?
| ;)
| enragedcacti wrote:
| If you think about it, the car analogy really is the
| Corolla of analogies.
| bil7 wrote:
| do you have some other anology we should all switch to? maybe
| a ferrari level analogy that's way better?
| pushingice wrote:
| The car analogy is the Ford Model T of analogies.
| bee_rider wrote:
| Car analogies aren't intrinsically bad, they are just the go-
| to analogy when someone wants to jam an analogy where it
| isn't needed. Analogies in general should be used sparingly,
| and only in an explanatory setting. Instead people use them
| as a rhetorical device in arguments, which usually reduces
| the argument to arguing about the analogy (and you can
| usually shuffle around the parts of an analogy to flip the
| meaning somehow).
|
| Here it is fine I think, the writer of the comment is just
| explaining their point of view.
| drewcoo wrote:
| > Car analogies aren't intrinsically bad
|
| What can I say? They get me from claim A to claim B.
|
| So are you saying that analogies should only be used like
| secondary steering wheels?
| bee_rider wrote:
| Analogies should only be used like trains: An efficient,
| well thought out path from point A to B on a vehicle that
| is piloted by a pro. Car analogies look appealing -- they
| look more flexible, but this can also lead to people
| taking overly circuitous routes to get to the point...
| maybe the driver just doesn't know what they are doing,
| maybe the road system is poorly optimized because it
| needs to hit lots of points, or maybe the driver is like
| a sneaky cab driver that intentionally takes an
| inefficient path to increase the fare.
|
| The wider availability also leads to a situation where
| cars are mostly piloted by random people with no
| particular qualifications other than a basic license.
| This can result in lots of car crashes. Of course, it is
| also possible for a train to get derailed, but this is a
| rare occurrence. On the other hand a derailing can result
| in more damage... ah... hmm, I forget where I was going
| with this...
| aeonik wrote:
| They only get you from claim A to claim B when there is
| enough traffic to invest in roads and if people follow
| the rules.
|
| A more versatile set of analogirs are of course ATVs,
| Aircraft, or even the humble legs.
| drewcoo wrote:
| > It's like a Toyota Corolla
|
| This is only an invitation to car-shedding!
| falcolas wrote:
| So it was. So it was indeed.
| valbaca wrote:
| Hit too close with the analogy:
|
| Been a Java dev for ten years and I drive a Toyota Corolla....
|
| ...but also in my spare time I play around with Clojure and
| dream of buying a '69 SS Camaro
| nly wrote:
| Admit it, you never will.
| TheRealDunkirk wrote:
| Well, maybe, like me, by the time you can afford it, your
| knees and back don't align with getting in and out of one.
| falcolas wrote:
| I appear to be you, just with a Subaru BRZ. It's a manual,
| it's fun as hell.
| therealmarv wrote:
| I'm extremely happy I have not had to use it beside one liners
| for the last 12 years of my professional freelancer career. I
| still remember the times when Java people were laughing at me
| when I was telling them that I'm mostly a python developer.
| teknopaul wrote:
| Trouble with java is that it does not scale up or down in terms
| of ram.
|
| Minimum RAM for a sever doing something normal over tcp is
| measured in gigabytes.
|
| Big servers > 16gb get difficult to manage at runtime.
|
| You have to scale with more VMs.
|
| You can write useful C servers that are very small, especially if
| you compile with musl. And run the same code for 1000kcc (not a
| typo)
|
| When you have big arrays of memory storing everything as
| Objects/pointers gets messy and inefficient. But any big heap is
| hard to manage and keep response times consistently low.
|
| My other gripe os that "write once run anyway" is no longer close
| to true, since Oracle. Mac, Linux x64 and Windows 64 are your
| only sane options. If you look at the compile targets list for c
| or rust you can see write once run anywhere working on a lot more
| cpus. True, you might have Arch specific code but it works, and
| most Java does not port from Linux container to Windows for
| example.
|
| A statically compiled Binary is often easier to move across
| systems, because a java app is rarely a single jar. It's usually
| >5gb of app specific jvm and libs and config files.
| Dracophoenix wrote:
| kcc in this context is "kilo clock cycles", right?
| Scarbutt wrote:
| _Minimum RAM for a sever doing something normal over tcp is
| measured in gigabytes._
|
| wut? do you mean MB? most small web services(jetty, jdbc/pg
| driver/json) I have work on use below 500MB
| ElectricalUnion wrote:
| > Trouble with java is that it does not scale up or down in
| terms of ram.
|
| > When you have big arrays of memory storing everything as
| Objects/pointers gets messy and inefficient. But any big heap
| is hard to manage and keep response times consistently low.
|
| Java can handle very large, TB-sized heaps (under normal
| circunstances, about 52TB). But when you're dealing with TB-
| sized heaps, anything is slow - including programs not made in
| Java.
|
| > You can write useful C servers that are very small,
| especially if you compile with musl. And run the same code for
| 1000kcc (not a typo)
|
| Anyone can build stuff with musl, but musl is in general a lot
| less optimized that GNU glib, so I guess it really only makes
| sense on resource-constrained environments - not those where
| you're handling TBs of heap.
|
| > A statically compiled Binary is often easier to move across
| systems
|
| I guess you're talking about jart/cosmopolitan here, not your
| average musl application - a statically compiled Binary usually
| needs to be recompiled to work on other systems.
|
| > because a java app is rarely a single jar.
|
| Uberjars are very common, the norm those days.
|
| > It's usually >5gb of app specific jvm and libs and config
| files.
|
| On my experience even if you "accidentally" bundled the whole
| Java SDK together with your app, you're not getting over 250MB
| for Java.
|
| Unless you're counting the whole OS, in that case, even the
| musl application isn't that small anyways.
| mihaigalos wrote:
| Anybody have experience with the JNI interop with native libs?
|
| Is it better to implement something natively in a compiled
| library and link it in from Java or better to rewrite it in Java?
| What about lifetimes of objects - who "owns" an object - the
| runtime or the lib?
| thex10 wrote:
| Being taught intro Java in high school (mid 2000s for me) was
| excruciatingly boring and caused me to write off majoring in
| computer science or working as a programmer.
|
| Today I'm a software engineer with experience in JavaScript,
| Ruby, Python, Elixir... maybe it's time for me to give Java
| another try.
| nailer wrote:
| > Being taught intro Java in high school (mid 2000s for me) was
| excruciatingly boring and caused me to write off majoring in
| computer science or working as a programmer.
|
| Same here. Nothing more to add.
| ramesh31 wrote:
| >Today I'm a software engineer with experience in JavaScript,
| Ruby, Python, Elixir... maybe it's time for me to give Java
| another try.
|
| Nah. If you _have_ to use it, Java 's really not that bad. But
| I would never choose it for a personal project. Its' strengths
| are in all of the concerns that come with enterprise
| development.
| rco8786 wrote:
| It's not. Java has slightly improved since that time, for sure,
| but you're not missing anything.
| afandian wrote:
| Try Kotlin. I love it. Feels like the best bits of Clojure,
| Ruby, Python and Java.
| seanmcdirmid wrote:
| Kotlin is great! I cringe when I have to go back to Java
| occasionally for some reason.
| commandlinefan wrote:
| You might want to start with C. C is a _lot_ more enjoyable to
| learn and use, and once you know C you basically already know
| Java. (Assuming you understand OO concepts in general, anyway)
| [deleted]
| [deleted]
| master_jonsie wrote:
| What does the Jet Propulsion Laboratory have to do with Java?
| naikrovek wrote:
| and it still enforces terribly strict OOP patterns onto the
| developer which is almost never the right way to develop software
| if you care about performance even a little.
| nailer wrote:
| Even if you don't care about performance and only care about
| simplicity OOP is really hard to rationalise about.
| commandlinefan wrote:
| Java has supported (mostly) functional programming constructs
| since 1.8 (which was 2014), so you can realistically use it
| without doing too much OO.
|
| I've observed, though, that people who complain about OO in
| Java usually write top-down procedural code rather than
| functional-style code, which is far, far worse.
| nailer wrote:
| I've observed that Java has a culture of OO, so people tend
| to be unaware of scopes, closures etc.
| bhuber wrote:
| I'm not sure you fully appreciate how tailored the JVM, and
| hotspot in particular, are to executing OOP oriented code. One
| great example I can think of is polymorphic methods. In C++ for
| example, you have to explicitly declare a class method as
| "virtual" in order for it to be polymorphic - i.e. the version
| called at runtime is tied to the runtime object instance, not
| the compile time type. This is because in order to do this in
| C++, there needs to be an extra lookup in the vtable to find
| the function address for every virtual function call at
| runtime. If C++ made all its methods virtual, it would take a
| significant performance hit from the extra vtable lookup for
| every function invocation.
|
| In Java, all methods are virtual by default. Java also does the
| equivalent of a vtable lookup at runtime for function calls,
| but it has something C++ doesn't have - the hotspot optimizer.
| For any call site that is executed enough to affect runtime
| performance, the hotspot optimizer will optimize away the
| vtable lookup if there are only 1 or 2 method versions called
| at that site at runtime. This is true for the vast majority of
| cases. For most of the other cases, where you have 3 or more
| possible method implementations that could be invoked at a
| given call site, you would probably have to have something like
| a vtable lookup at that call site whether you use OOP or not
| (switch statement, if-else, explicit table of function
| pointers, etc), so you're not losing performance there either.
| The end result is, the JVM gets polymorphic methods basically
| for free in terms of performance.
|
| This is just one example, there are many other clever things
| the JVM does to make OOP code performant. I don't have a
| citation, but I do recall seeing a talk (maybe by James
| Gosling?) where he mentioned that one of the primary design
| goals of Java was to make "doing the right thing" from an OOP
| perspective also the best option for performance.
| naikrovek wrote:
| it doesn't matter how much the HotSpot JVM is tailored to OOP
| code. CPUs and RAM are not tailored to OOP in any way.
|
| Procedural code will always be more efficient with CPU and
| RAM, arrays will always be faster than Lists, being able to
| control datatype sizing to the byte will always outperform
| classes, and so on.
|
| java is very fast, please do not misunderstand me. java is
| much better than it used to be, as well.
|
| Java is not a language chosen when performance is a concern.
| Java is chosen when you have a giant pile of developers of
| various levels of skill and you want to pile a ton of rules
| and linters on them all so they write software in the same
| way.
| bhuber wrote:
| > it doesn't matter how much the HotSpot JVM is tailored to
| OOP code
|
| This is obviously false. The JVM, or any other compiler for
| that matter, is what translates the OOP code into CPU
| instructions. If it does that optimally, it won't matter
| what design pattern the top-level compiled language used.
| If it does it poorly, then it will.
|
| > CPUs and RAM are not tailored to OOP in any way.
|
| This is not entirely true. Intel in particular pays a lot
| of attention to Java performance when benchmarking
| processor designs, see for example https://www.intel.com/co
| ntent/www/us/en/developer/articles/t... .
|
| > Procedural code will always be more efficient with CPU
| and RAM...
|
| First of all, arrays vs Lists and data type sizing are
| orthogonal to procedural vs OO code. You can write OO code
| that uses arrays and procedural code that uses lists, and
| datatype sizing is more related to your choice of language
| and compiler toolchain than your design patterns.
|
| I think what you're trying to say here is that the
| performance _ceiling_ for a low level language using simple
| language primitives (if-else and vanilla function calls
| instead of classes and polymorphism) that compiles to a
| binary is higher than that for a high level language that
| compiles to an intermediate language (or an interpreted
| language). This is generally true for small code paths - if
| you need to do a bunch of matrix operations, or data
| crunching for a small well defined problem, you can
| generally do it faster in C /C++ than in Java if you put in
| enough effort. The ceiling part matters though - in
| general, you have to put in a lot of skill and development
| effort to realize these differences, and this often grows
| super-linearly with the size of your codebase for low level
| languages. If you have a large application that has a lot
| of code, your overall performance will usually be higher
| with a high level language because the _average_
| performance for any particular part will be much better.
| Sure, given infinite time and resources you could
| theoretically do better in C, but nobody has that.
|
| This is reflected in the approach most professionals take
| in practice when it comes to perf optimization - write most
| of your code in a high level language like Java or Python
| because on average it will be faster and less buggy for any
| reasonable amount of developer effort. For pieces of code
| that absolutely have to run as fast as possible, write them
| in C and call out to them from the high level language.
|
| I guess the point I'm trying to make here is lots of people
| choose java precisely _because_ performance is a concern.
| It does better than most other high level languages out
| there, and your average performance for a large codebase
| will be much better than something like C /C++ given the
| same amount of effort. As others have noted, it does
| multithreading better than most too, which is another major
| performance consideration. I don't care if my Java code is
| half the speed of the C equivalent if I can easily run 40
| cores at once - or 40000. I think languages like Rust and
| Swift may let us have the best of both worlds in the
| future, but that remains to be seen. For now, the only time
| lower level procedural languages win is when you need a
| relatively small codebase to run absolutely as fast as
| possible.
| twblalock wrote:
| OOP is fine. OOP and functional programming written by skilled
| programmers both end up being basically the same thing -- they
| are just different techniques to achieve encapsulation, control
| over dispatch, control over state, etc.
| jayd16 wrote:
| What can't you do in Java that you want to do besides the fact
| that there's no stack allocated type (which is a java thing but
| not an oop thing)?
| kaba0 wrote:
| (Nitpick, but primitives are stack-allocated)
| exabrial wrote:
| The CDI specification is what takes Java from "good" to
| "incredible". The dependency injection pattern makes Java a
| hybrid functional language, where all the state can be stored in
| the CDI container. This eliminates a whole class of bugs and
| simplifies a codebase allowing for pervasive use of composition.
|
| Stuff like Microprofile, Quarkus, ActiveMq, Tomcat, and even
| JakartaEE are gravy on the cake.
| pid_0 wrote:
| mark_l_watson wrote:
| Sun Microsystems had a link to my blog on the Java home page for
| about a year. I had attended the first Java World Tour, blogged
| about it, and for 15 years I was the first "hit" searching for
| "Java consultant". Thank you Java.
|
| All that said, I don't use Java much anymore, preferring to use
| Clojure when I need the rich JVM ecosystem. I do follow new Java
| language features and usually try them.
| jrsj wrote:
| After mostly using Node and Go for the last 3 years I kind of
| miss Java honestly. Unfortunately it's still terminally uncool in
| my local job market so even mentioning it would be a bad career
| move.
| mkl95 wrote:
| I wrote a lot of small Java programs when I was in school, and
| Eclipse felt like being on developer steroids compared to using
| an IDE with a dynamic language. My software just worked and was
| pretty fast. I have mostly worked with Python since I became a
| pro developer and I often wish it was a more "boring" language.
| pdntspa wrote:
| I recently started a side new project in Java targetting GraalVM
| with language version 17.
|
| Aside from Java's innate finickyness, it has been an unexpected
| pleasure. I think a lot of it has to do with its static typing (I
| typically work in dynamic languages, and it's nice knowing that
| if the program compiles it likely works), and how simple the
| language keeps its primitives.
|
| But you need really good tooling to use it, like a powerful IDE
| with good autocompletion and refactor support. It is way too
| verbose to type everything out yourself, and the verbosity means
| manually refactoring takes lots of changes around the program to
| manifest.
|
| The sheer amount of code out there to import is immense, there
| seem to be libraries for anything and everything!
|
| So far, it seems like the time I lose to its pickiness, I gain
| back with IDE features, static typing, and the ease of
| understanding it (because it is so verbose).
|
| I'm also not hot on how it seems to steer everything into a
| factory pattern, but so far I've been able to avoid that for most
| things.
| hedora wrote:
| My main problem with Java is that it's picky, and has some
| static typing, but it also has heaps and heaps of loopholes in
| the type system (that turn into runtime exceptions), so it's
| this weird compromise where everything is substandard. I've
| found that Go "feels" a lot more like a dynamically typed
| language, but still has the good IDE support that you're
| talking about.
|
| If you want to see how much progress there has been in
| production-quality statically typed languages, write some
| multithreaded code in Rust. In addition to being memory safe
| without a GC, the compiler also confirms that your code is
| threadsafe.
|
| Both those guarantees can be violated using the "unsafe"
| keyword; Java has similar mechanisms that break memory safety.
| Java doesn't provide meaningful thread safety, in the same way
| that C's malloc/free don't provide meaningful memory safety --
| it's possible to write thread- and memory-safe programs in both
| languages, but the Java compiler doesn't really help out much
| with thread safety, just like the C compiler doesn't typically
| check for use-after-free, etc. Go's thread safety semantics are
| closer to Java's than Rust's (though multithreaded programming
| in Go is more ergonomic than in the other two languages).
| pdntspa wrote:
| I've read enough critiques of Rust to be put off from trying
| it out at this time. And there's a lot of things I don't like
| about Go. (Zig is interesting though)
|
| Unfortunately Rust doesn't have the kind of library support
| that Java does, and I don't really want to roll my own on
| some things (the side project will never get done if I get
| lost in the weeds)
|
| For this project the choice fell between Java and C#, and
| Java won because I was familiar with the library code that
| does what I want to do.
|
| Besides, Java has Swing, which is about the only cross-
| platform GUI toolkit I can stand to work with (GTK as a close
| second)
|
| > but it also has heaps and heaps of loopholes in the type
| system (that turn into runtime exceptions)
|
| I've yet to run into this in places where I don't really
| expect it. Do you have some examples of where this becomes a
| problem? I wrote a bunch of reflection code that triggered a
| lot of RuntimeErrors, but that was foreseeable as its
| reflection, the whole point is to figure out types and
| whatnot during runtime. And at that point, I just fall back
| to how I write code in dynamic languages.
| kaba0 wrote:
| > In addition to being memory safe without a GC, the compiler
| also confirms that your code is threadsafe.
|
| No, not at all. Rust verifies that your code has no _data-
| races_. That is an absolutely tiny subset of all race
| conditions, that are simply not verifiable statically.
| dehrmann wrote:
| > But you need really good tooling to use it, like a powerful
| IDE with good autocompletion and refactor support. It is way
| too verbose to type everything out yourself, and the verbosity
| means manually refactoring takes lots of changes around the
| program to manifest.
|
| One of the ironies of Java has been that its strictness and
| verbosity can make it hard to develop, but that strictness also
| enabled the development of powerful IDEs. What feels like a
| hassle for a 100 line file becomes an asset for a million-line
| project because of the safety, discoverability, and refactoring
| it enables.
| gorjusborg wrote:
| > What feels like a hassle for a 100 line file becomes an
| asset for a million-line project
|
| This is true and hard to communicate to people that haven't
| lived it.
| kuboble wrote:
| Yes. I worked many years in both Java and C#. In Java every
| project and codebase I saw was pretty much the same.
|
| In c# when I look at other people's projects I often feel
| like it's a foreign language. You can make it look like C++
| with unsafe blocks. You can nake it look like ruby with
| dynamic variables. You can write sql-like statements.
|
| As much as I love writing in C#, I prefer reading other
| people's Java.
| pdntspa wrote:
| Indeed; I haven't seen a ton of bad code in it (not saying
| that it's not out there, just that I haven't been exposed to
| much of it), but when I needed to dig into how something
| works, so far it has been very easy to scan and mentally
| parse what's going on.
| binkHN wrote:
| Have you explored Kotlin? It's really not just for Android.
| nerdponx wrote:
| I've heard from a few corners that Kotlin is "Java but
| better", but I've also heard that the tooling is pretty
| lacking if you aren't using JetBrains stuff. True?
| dboreham wrote:
| Successfully used VSCode for Kotlin projects.
| [deleted]
| pdntspa wrote:
| I have, it's a nice language but I didn't like the mental tax
| of translating Java code to Kotlin in my head whenever I had
| to read up on how to do something
|
| I do intend to dig into it a bit more once I feel like I have
| mastered Java
| binkHN wrote:
| I hear you, and had to do the same for a while. Eventually
| your brain migrates over and it becomes second nature. The
| ability to copy Java code and paste it as Kotlin helps
| tremendously, especially in the beginning.
___________________________________________________________________
(page generated 2022-08-09 23:01 UTC)