Is inheriting from a primitive array impossible from the JVM's perspective?
Asked Answered
B

3

7

Well my doubt is this one:

In Java, it is disallowed to inherit from an array, ie, one can't do things like:

class FloatVec extends float[]
{
    // Vector methods.
}

FloatVec somevec = new FloatVec()[] { 1, 2, 3 }; // With array initializer.

Or even better:

class FloatVec3 extends float[3]
{
    // Regular accessor.
    public float getX() {
        return this[0];
    }
    // Or say, make it the 'this' implicit like with other fields:
    public void setVec(float x, float y, float z) {
        [0] = x;
        [1] = y;
        [2] = z;
    }
    // And specific vec3 methods like:
    public float dotProduct() {
        float x = this[0];
        float y = this[1];
        float z = this[2];
        return x * x + y * y + z * z;
    }
}

But arrays actually implement a specific interface and are considered objects. ie, one expects of array instances the same methods exposed by Object, plus a specific array field, the final 'length' field.

So my question are, even if the Java language disallows this usage:

  • Could it be implemented in the JVM without too many changes?

  • Does the JVM treats arrays like any object with a class that can be inherited from?

  • Does the JVM treats arrays like enums, ie, making the array objects inherit automatically from a defined array class?

  • Is the array class defined somewhere in such a way that it could be inherited from?

Barbera answered 8/11, 2014 at 22:6 Comment(2)
Considering that other languages can be implemented on top of the JVM, and that all you need in this case is some kind of "type erasure" (when you want to pass these arrays to APIs expecting "regular" arrays) and boxing (when you receive results), I cannot see why it couldn't be done... From the compiler's perspective, of course, this is a lot more tricky... (disclaimer: I'm not a Java guy)Teetotaler
That's what got me thinking. Say that the VM makes assumptions about arrays layout in memory since they're fixed. For example, 'length' field is at 12 byte offset into the object, data begins at 16 byte offset, ends at 'length' * bytes per element after that. Regular array operations could work on those assumptions. If it doesn't makes assumptions about what lies beyond the array's data, you could append all the fields of your inherited class after that and call it a day. Then again, resolving the location of those extra fields might differ from how regular object fields are resolved.Barbera
D
8

Could it be implemented in the JVM without too many changes?

No. The changes would be massive. They would impact the entire Java tool chain, and also a huge body of 3rd-party code the works at or below the JLS / JVM abstraction layer.

There is nothing stopping you from downloading the (OpenJDK) source code and trying to do this yourself as an experiment. But the chances of this happening in real Java are (IMO) vanishingly small.

I've listed just some of the technical problems at the bottom. I'm sure that there are others.

Does the JVM treats arrays like any object with a class that can be inherited from?

No.

Array types in Java provide a small number of methods. (The methods are getClass, hashCode, toString, clone, wait, notify and notifyAll ... as per the Object API.)

As far as I know, the actual implementations of these methods are provided by the native methods defined by java.lang.Object. But since the JLS does no permit you to write code that inherits from an array, the JVM spec doesn't need to provide a way to implement such code. And, in practice, it doesn't.

Does the JVM treats arrays like enums, ie, making the array objects inherit automatically from a defined array class?

No. Array types implicitly inherit from java.lang.Object.

Is the array class defined somewhere in such a way that it could be inherited from?

No such class exists. Array types implicitly inherit from Object.


At the JVM spec level, there are a couple of major impediments to making arrays more "class-like":

  • The "type string" representation of an array type ("[elem-type") only mentions the element. The actual array type has no name, and if it did then the "Lname;" representation is saying that this is a regular class, not an array type.

  • Arrays are created by special JVM instructions that provide the element type as an operand not the array type.

And beyond that, a JVM implementation is going to assume things about how arrays work in order to implement them efficiently. Even though (according to the JLS) it appears to theoretically possible to use an invoke instruction to call a non-standard method on an array, a JVM interpreter or JIT compiler wouldn't know what to make of it ... even if you somehow managed to sneak the invoke past the class loader and verifier.

Once you get past that, then there is that problem that if arrays could be declared with user-defined superclasses, then those superclasses would (presumably) be able to have instance variables. But that implies that the JVM spec needs to change so that:

  • the heap nodes for arrays can hold instance variables as well as the array itself,

  • the regular field load and store instructions work on array objects as well as reculare objects,

  • and so on.

As you can see, this "small extension" unravels a whole lot of other design decisions in the JVM.

Dilator answered 8/11, 2014 at 23:4 Comment(1)
Wasn't me. I +1'd the heck out of you. :)Giesecke
G
6

Does the JVM treats arrays like any object with a class that can be inherited from?

Each primitive array type does indeed have a class. For example, an int[] actually is an instance of int[].class and a float[] is an instance of float[].class. (JLS 10.8) You can see in your own code sample that these classes cannot be inherited from.

Does the JVM treats arrays like enums, ie, making the array objects inherit automatically from a defined array class?

Yes, if you have two int[] arrays, say a and b, then a.getClass() == b.getClass().

Is the array class defined somewhere in such a way that it could be inherited from?

As you can see in your own code example, these classes cannot be inherited from. They have no source code and are created by the JVM itself, as said in this other answer along with a code example.

Could it be implemented in the JVM without too many changes?

This question is outside of the scope of Stack Overflow and is very subjective.

Giesecke answered 8/11, 2014 at 22:20 Comment(5)
This is a great answer but it is geared more towards the language specification. The question asks specifically about virtual machines.Hulse
@Hulse Good point. I was trying to answer the question as objectively as possible, and in reading it I felt that "does/could the JVM do XYZ" questions weren't answerable like that, since a JVM is free to implement any functionality from the JLS in whatever way it likes. This is further reflected in the asker's assumption that there's only one JVM implementation.Giesecke
I suppose it would have been more appropriate for me to vote-to-close rather than attempt to answer the question.Giesecke
Usually I opt to vote-to-close this type of question as well but this one is so very well asked. ; )Hulse
I didn't meant to imply there was a single JVM, but it was more targeted to actual current JVM implementations. ie, what could be done with what its already out there and widely used. With new JVMs one could do anything, but Java spec tends to go in tandem with OpenJDK development, thus why Hotspot specific details are welcome. Then again, if someone wanted to explain how this could be achieved in Dalvik, I wouldn't mind either :)Barbera
B
1

The closest that you could get to this in Java is Gil Tene's ObjectLayout project - http://objectlayout.org/ - this is still a long way from making it into Java, but it's just possible that this will make it as part of Java 9

Bolzano answered 17/12, 2014 at 16:34 Comment(3)
I think the simplest way to adapt the JVM for enhanced arrayish things would be to have a type which represents the concatenation of an array of references and an array of primitives. Such a type could, with compiler support, be used to represent the concatenation of a header plus an arbitrary number of elements, with the header and elements each containing an arbitrary collection of "fields". Things of that type would not be suitable for use in most public interfaces, but could cut in half the number of indirections required to access many kinds of data.Issacissachar
Supercat: I'd go & discuss it with the ObjectLayout folks - they're a friendly lot & I'm sure they'd like to hear about your use case.Bolzano
I didn't see where discussion was solicited over there; perhaps I missed something? Otherwise, one of the things I'd like to see as an adjunct to the "intrinsic" concept would be for Oracle to add a few "uncommitted" fields to Thread, so that "intrinsics" without too many fields could be used as method return values [e.g. a method could return a type Point2d consisting of int x; int y; by e.g. storing x into CurrentThread.tempI0 and returning y], rather than having to create a new instance of a Point object and hope the JVM optimizes it away.]Issacissachar

© 2022 - 2024 — McMap. All rights reserved.