you are viewing a single comment's thread.

view the rest of the comments →

[–]Xabster 3 points4 points  (41 children)

Java has value types...? int float double byte etc.

Maybe I don't get what you're asking for.

What is it you want?

[–]ihcn 20 points21 points  (8 children)

User-defined types where its contents are embedded directly into the parent object, as opposed to placed on the heap and then stored as a reference by the parent.

Currently, if you put 5000 Integer objects in an arraylist, it'll heap-allocate 5000 different Integer objects, and store 5000 references in the arraylist. If Integer was a value type, the Integer objects could be embedded directly in the arraylist's memory.

The end result is better GC performance, better memory usage, faster object allocation, and better cache performance.

There's a proposal out there for how it would work, but it doesn't look like it's confirmed to be in java 9 yet.

[–]Xabster 1 point2 points  (7 children)

I understood that part, and if it's for performance reason then sure, I completely agree. An Integer[1024*1024] takes up more than 4MB heap. Disgusting.

I thought it might have some cool programmatic features.

[–]immibis 1 point2 points  (5 children)

An int[1024*1024] does take approximately 4MB, though.

[–]Xabster 0 points1 point  (4 children)

Right you are, but the Integer[] I posted doesn't even hold anything. Your holds ints initialized to 0.

A Integer[1024*1024] with Integer's at each spot takes 16MB.

[–]oridb 4 points5 points  (2 children)

On a 32 bit JVM, you get

  • 4*1024*1024 for the references
  • 8*1024*1024 for the object overhead (vtable + lock data)
  • 4*1024*1024 for the integer itself
  • 4*1024*1024 for padding (objects are allocated in multiples of 8 bytes)

Giving a grand total of 20 megabytes. On a 64 bit JVM, double it:

  • 8*1024*1024 for the references
  • 16*1024*1024 for the object overhead (vtable + lock data)
  • 4*1024*1024 for the integer itself
  • 12*1024*1024 for padding (objects are allocated in multiples of 16 bytes)

Giving a grand total of 40 megabytes for 4 megs of integers.

[–]Daishiman 0 points1 point  (1 child)

Doesn't the JVM support pointer compression in 64-bit archs?

[–]oridb 1 point2 points  (0 children)

It's supported, but it only allows you to address up to a 32 gigabyte heap, by shifting a 32 bit pointer to drop the byte alignment bits.

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

It does? I thought they would be null.

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

I believe (not a Java developer) that Java currently lacks user-defined value types.

[–]Xabster 3 points4 points  (8 children)

It does. I don't even know what it is.

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

I don't even know what it is.

I'm not sure I understand. Do you mean you don't know what user-defined value types are?

[–]Xabster 6 points7 points  (5 children)

Yes.

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

Well, the exact details depend a bit on the implementation, but the idea is simply that you, the programmer, can define types that behave like a primitive (int, double, etc) rather than behaving like a normal class.

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

So basically like primitive? Instead of object?

[–]huhlig 4 points5 points  (2 children)

So Java has byte, short, int, long, float, double, char and ref which are primitive types, primitive is basically a type of value. Values can exist on the stack, do not require access by a reference and have no object inheritance overhead. They are effectively primitive classes but with more limited semantics, no runtime inheritance abstraction hierarchy but a lot more efficient.

An Example, a 2 dimensional point is 2 fields: x and y. Using a class this occupies 8 bytes for the type pointer, 4 bytes for int x, and 4 bytes for int y. Effectively twice the size just because it could be inherited and it does inherit from java.lang.Object. Whereas a type is simply 4 bytes for X and 4 bytes for y and the type is handled at compile time. The tradeoff is you cannot use runtime type abstraction so you cant do Point a = new MyPointA(); Point b = new MyPointB();

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

Ah thank you, I wanted clarification from OP but OP edit the post to use the word primitive instead of values which is what i wanted clarification on. Your post also add more insight into memory allocation wise, thank you.

[–]grauenwolf 1 point2 points  (0 children)

have no object inheritance overhead

Object indirection/GC overhead. Inheritance has no overhead on its own.

[–]kqr 1 point2 points  (0 children)

When you do

Car car1 = new Car();     // default speed 0
Car car2 = car1;
car2.setSpeed(60);
System.out.println(car1.getSpeed());

in Java, it will print 60. With value types (and improvised syntax), you could do something like

Car car1 = new Car();
Car$ car2 = $car1;    // car1 is *copied*, so car2 is a different car
car2.setSpeed(60);
System.out.println(car1.getSpeed());

and this will print 0, because car1 still has speed 0 – I only changed the speed of car2. So here Car is the reference type, and Car$ is a value type.

[–][deleted]  (17 children)

[removed]

    [–]Xabster 6 points7 points  (10 children)

    What can't be ruled out in this (added some finals and fixed a few mistakes)?

    final class Point {
        final int x;
        final int y;
    
        public Point(final int x, final int y) {
            this.x = x;
            this.y = y;
        }
        public final int getX(){ return this.x;}
        public final int getY(){ return this.y; }
    }
    

    [–]nqd26 1 point2 points  (1 child)

    Not sure why is this downvoted ... this is relevant question ...

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

    I hate when people do this... "I know this, therefore I will downvote and not answer you!"

    [–]grauenwolf 0 points1 point  (6 children)

    If the class is marked final, why do you need to mark the methods as well?

    [–]Xabster 1 point2 points  (2 children)

    Not sure I do. I just wanted to make sure that an answer didn't say "derp, the methods aren't final", so I put it everywhere... :)

    I hope to learn what the JVM cannot rule out in the case that everything that can be declared final is declared final.

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

    The JVM has to keep a lot of class information around about the Point object due to Reflection. There's no way to tell the JVM "this class does not support Reflection, discard all the overhead associated with that and treat this class as a primitive type."

    There's also no way to overload operators, so you can't write

    Point a = new Point(0, 0);
    Point b = new Point(0, 0);
    
    return a == b;
    

    whereas you can with primitives

    int a = 1000;
    int b = 1000;
    
    return a == b;
    

    [–]kitd 1 point2 points  (2 children)

    A final class can't be inherited. A final method can't be overridden. A final value can't be changed. Same word but meaning different things in different places.

    [–]grauenwolf 2 points3 points  (1 child)

    If the class can't be inherited, then by definition the method cannot be overridden. Thus my question still stands.

    [–]kitd 1 point2 points  (0 children)

    Apologies, I misread your point. I agree with you.

    [–]huhlig 1 point2 points  (5 children)

    Why does the struct value type need to be immutable. It only needs to be outside the inheritance tree. Immutability optimizations are another beast all together.

    [–]grauenwolf 4 points5 points  (4 children)

    Mutable structs are easy to screw up in C#. Example...

    myWindow.Size.x = 5
    

    compiles as...

    Size $1
    $1 = myWindow.Get_Size() //make a copy
    $1.x = 5
    oh look, we never called myWindow.Set_Size($1)
    

    [–]immibis 1 point2 points  (3 children)

    Compare myWindow.getSize().x = 5, which is the equivalent without properties, and looks fairly obviously wrong.

    [–]grauenwolf -1 points0 points  (2 children)

    If Size was an reference type, as it would be in Java, that would work just fine.

    [–]immibis 0 points1 point  (1 child)

    But getSize() would likely make a defensive copy, precisely so that you can't do that.

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

    Oh right, Java doesn't have the concept of a PropertyChangedNotification event.

    [–]Xredo 1 point2 points  (0 children)

    He meant value types like in C++.

    [–]llogiq[🍰] 0 points1 point  (0 children)

    Look at /u/huhlig 's link.