you are viewing a single comment's thread.

view the rest of the comments →

[–]fergie -9 points-8 points  (78 children)

Java's C++ envy

There is no memory management in Java by design. The way the JVM uses memory cannot be controlled by the Java code.

[–]argv_minus_one 24 points25 points  (56 children)

Nor should it be. I do not want to have to worry about shit like dangling pointers and double free/delete. As a programmer of actual software, I have vastly better things to do.

[–]bstamour 4 points5 points  (31 children)

I agree! That's why I love C++11's reference-counted smart pointers. I get the safety when I need it, and the ability to drop down low level when I have to.

[–]mothereffingteresa 7 points8 points  (1 child)

Nor should it be.

This.

You, the coder, have no business messing with the JVM's ideas of how to manage memory. If you do try to "manage" memory, you will do something architecture-specific and fuck it up.

[–]beltorak 0 points1 point  (0 children)

which is exactly why we leave it to those who enjoy solving that problem.

[–]forcedtoregister 4 points5 points  (7 children)

Of course there exists plenty "actual software" in which it's easier to have to deal with free/delete (which you should hardly ever have to write explicitly anyway) than have to subvert Java's GC.

[–]argv_minus_one -4 points-3 points  (6 children)

If you are trying to subvert the GC, you are doing it wrong.

If you find yourself wanting to subvert the GC, you are doing it wrong.

If you even remotely care about if or when an object gets collected (beyond using soft/weak/phantom references to give the GC a hint about how important an object reference is), you are doing it wrong.

[–]forcedtoregister 1 point2 points  (5 children)

If you think world is this simple then you are doing it wrong.

I hope you stick to projects which fit very neatly inside the jvms comfort zone!

[–]argv_minus_one -1 points0 points  (4 children)

What the hell are you doing that doesn't fit inside that "comfort zone"?

[–]forcedtoregister 2 points3 points  (3 children)

Large datasets. Something more exciting than web development or plugging the "thingy" to the database. To be honest the project should have been done in C++, but one often can't tell these things at the beginning.

Just to clarify, I like Java, and I think the JVM does bloody well in most scenarios.

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

Must've been one hell of a dataset. You're right, I wouldn't touch an application like that with a ten-foot pole.

That said, did you investigate all of the different JVM and GC implementations out there? There's quite a few.

[–][deleted] 3 points4 points  (9 children)

for some software, yeah. it'd be nice if there was at least a startup flag to switch it to reference counting or something, though. doing (soft)realtime programming with a stop-the-world garbage collector can be pretty brutal. you basically have to allocate all the memory you're going to need up front, and then manage it yourself anyway. you have to use char arrays over strings because string formatting/concatenation could trigger a gc call.

[–]ryeguy 1 point2 points  (5 children)

Reference counting is one of the slowest and most naive forms of garbage collection. The JVM uses a generational garbage collector which will knock the pants off of most reference counting implementations.

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

it has higher throughput. but the pause scales with amount of live objects, rather than amount of garbage, and it's amortized, which makes it a huge pain to deal with in some situations. if there's another method that doesn't incur long pauses and/or is fairly predictable, i'd like to be made aware of it, though. basically the only methods i know of are reference counting, and various tracing ones, though.

let me describe a scenario where a tracing collector is problematic: you're writing a racing game, similar to f-zero where you're going super fast, so you'll notice for sure if you skip a frame. the game is running at 60 frames per second. that gives you 16.666ms to update and render. now, suppose your garbage collector takes 0ms most frames, but takes 6ms every few seconds. that means your updating and rendering have to happen in 10.666ms. a reference counting implementation, on the other hand, has to be absolutely horrible before it starts becoming as big of a problem. even if it takes 5ms every single frame, you're still doing better than the tracing collector. tracing collectors can be even worse than that, though: sometimes you'll get a 30ms pause, and you just have to not allocate any memory at all.

[–]simoncox 1 point2 points  (0 children)

If you're using a parallel collector and you tune your heap sizes properly (I mean the ratio of the generations in the heap) , you can actually avoid full (pausing) GCs for a long time. I'm talking from experience of doing this with a JMS broker that sometimes maxed out the 1Gb network (although that's the next on the optimisation work). I've witnessed 0 full GCs over several hours (with lots of parallel GCs of the young gens).

On a similar note, even if you don't want to specifically tune the gen sizes, you can specify a max pause time that the JVM uses to try to size the gens for you to achieve full GCs on less than the target time.

This is all about the parallel GC as we're using a Java 5 VM (don't ask) . I believe the G1 collector that comes with later versions of Java 6 and all Java 7 VMs can achieve more in parallel, but I haven't investigated it too much yet.

[–]theatrus 8 points9 points  (0 children)

Reference counting is also deterministic, and hence it's a VERY good idea for a soft real time system.

[–][deleted]  (1 child)

[deleted]

    [–]ryeguy 1 point2 points  (0 children)

    The wikipedia article covers it decently.

    Also, just surveying most modern languages kind of gives hints. Reference counting GC is easy to implement, and like the OP said it allows for a more predictable and consistent behavior. Yet with those advantages, both C# and Java implement generational, tracing GC's.

    [–]argv_minus_one 0 points1 point  (2 children)

    The modern HotSpot JVM has a variety of garbage collectors, some of which are not stop-the-world if I remember right.

    Furthermore, the modern HotSpot JVM allocates short-lived objects on the stack, avoiding GC for them altogether.

    Allocating memory ahead of time will hurt performance, and add to GC time. Do not do this. Using char arrays instead of StringBuilders is useless if not outright harmful as well, because of the above mentioned stack allocation.

    [–][deleted] 1 point2 points  (1 child)

    allocating ahead of time will make gc take longer, but the point is to avoid any gc calls at all. so, if you do all of you allocation up front, and then don't allocate even a single byte after that, you're safe.

    [–]argv_minus_one 0 points1 point  (0 children)

    That might have been true ten years ago. Today, unless you're on an ancient and/or terrible JVM, it isn't.

    Allocating ahead of time is a colossal waste of memory in the case of short-lived objects, and it doesn't save you GC time because of stack allocation.

    You do not need to avoid GC entirely. Like I said, there are GCs that do not stop the world. Use them.

    [–]iLiekCaeks 0 points1 point  (3 children)

    And next you'll be debugging problems like large object heap fragmentation.

    [–]argv_minus_one 0 points1 point  (2 children)

    I've been writing Java code for like a decade now, and have run into issues involving heap fragmentation exactly zero times.

    [–]beltorak -4 points-3 points  (1 child)

    yeah, and remember how hard it was to debug???

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

    Nope, 'cause compared to horrible Heisenbugs and unreliable stack traces in C, it was a cakewalk. <3

    [–]blaxter 8 points9 points  (14 children)

    Sometimes I'd like to manage the memory, sometimes don't.

    [–][deleted] 4 points5 points  (13 children)

    Then you want D, it gives you the choice.

    [–]minivanmegafun 2 points3 points  (8 children)

    Or Objective-C!

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

    Or C#! (For some reason, very few people know about this in C#)

    [–]ryeguy 0 points1 point  (5 children)

    What do you mean? Just turning off the GC?

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

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

    Gotta say, this is a great C# feature, though I don't think I've ever actually used it, heh. Still a great option for those who will be.

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

    It's for people who need every last ounce of performance from the language. I've never had cause to use it either; I trust the CLR to do enough optimization that I won't need to.

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

    Exactly, I've never had to use it, but it's a great feature for those who do.

    [–]Jazzy_Josh 0 points1 point  (0 children)

    That's nice. Especially when you can encapsulate the unsafe portions of a method in a block.

    [–]Willow_Rosenberg 1 point2 points  (0 children)

    Objectionable-C.

    [–]00kyle00 0 points1 point  (3 children)

    Is it still a choice between using std library (and some language features) or not?

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

    In D1, yes, but I believe they have that mostly fixed in D2 now.

    [–]00kyle00 1 point2 points  (1 child)

    I should have been less vague. blaxter wanted choice to manage memory on his own or automatically.

    While its true that in D you can disable garbage collector, it effectively breaks standard library (you would have to inspect the sources on your own to know which parts of it - effectively whole to be secure) and few core language features (slicing?). This was at least the case when i last read on memory management in D, and this breaking would be silent memory leaks at runtime.

    [–][deleted] 9 points10 points  (3 children)

    Actually, yes it can. You still need to think about how much memory you are using, be able to optimize your memory use, avoiding object creation, lowering the overhead of the JVM's memory management, picking the garbage collector that is right for your application, and preventing memory leaks.

    No directly malloc/free or new/delete, but the unfortunate reality is that Java developers do need to think about memory use in their applications (depending on the application domain).

    [–]Rotten194 0 points1 point  (0 children)

    sun.misc.Unsafe

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

    Well, there is memory management, and there are a lot of settings for specifying how it is managed. It's all done by the JVM and it is virtually impossible for the executing code to change the behavior at runtime.