1

I know that a lot of interpreted higher level languages like to abstract a lot of things and therefore cannot directly be compared with lower level constructs.

For example in some languages primitive values are implemented as references to value-objects. Most famously in Python.

When I learned programming, I was taught that primitives are simple values with a certain predefined size that get stored directly at an allocated memory address. I guess this is pretty much what happens in C/C++.

int a = 4; // put 4 directly at a memory location on the stack

Reading the specification of the JVM, it seems like they demand the same behavior.

https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html#jvms-2.6.1

A single local variable can hold a value of type boolean, byte, char, short, int, float, reference, or returnAddress. A pair of local variables can hold a value of type long or double.

Local variables are addressed by indexing. The index of the first local variable is zero. An integer is considered to be an index into the local variable array if and only if that integer is between zero and one less than the size of the local variable array.

A value of type long or type double occupies two consecutive local variables. Such a value may only be addressed using the lesser index. For example, a value of type double stored in the local variable array at index n actually occupies the local variables with indices n and n+1; however, the local variable at index n+1 cannot be loaded from. It can be stored into. However, doing so invalidates the contents of local variable n.

So this sounds very specific with little room to implement another way (for example as references to Java Value-Objects). Is this correct, or is this still up to the acutal implementation?

2 Answers 2

6

The very first sentence of the chapter you quoted, Chapter 2. The Structure of the Java Virtual Machine says [bold italic* emphasis mine]:

This document specifies an abstract machine. It does not describe any particular implementation of the Java Virtual Machine.

The next paragraph says:

To implement the Java Virtual Machine correctly, you need only be able to read the class file format and correctly perform the operations specified therein. Implementation details that are not part of the Java Virtual Machine's specification would unnecessarily constrain the creativity of implementors. For example, the memory layout of run-time data areas, the garbage-collection algorithm used, and any internal optimization of the Java Virtual Machine instructions (for example, translating them into machine code) are left to the discretion of the implementor.

In the past, there were two projects implementing a JVM in Ruby, Ruva and Rava [GitHub]. I can say with 100% certainty that neither of those two implements the local variable array as a contiguous memory region of primitive values, for the simple reason that Ruby doesn't have primitive values nor does it allow you to access memory.

In general, programming language specifications expect implementors to follow an AS-IF rule: you can do whatever you want, as long as the result appears to be AS-IF you had implemented the algorithms and data structures of the specification verbatim. For example, the ECMAScript Language Specification contains many algorithms written in low-level step-by-step pseudo code that could be directly translated 1:1 into an implementation – but the spec does not require or even expect you to do that:

The specification often uses a numbered list to specify steps in an algorithm. These algorithms are used to precisely specify the required semantics of ECMAScript language constructs. The algorithms are not intended to imply the use of any specific implementation technique. In practice, there may be more efficient algorithms available to implement a given feature.

While I did not find a similar statement in the JVMS at first glance, this is a common thing for many language specifications. In the Java world, compliance with the specifications is demonstrated by passing the test suites from the Java Compatibility Kit (JCK), which only test externally visible behavior.

1
  • Thank you for that elaborate answer. So the specification gives you a model of what the language looks like. Programmers can act as if the language was implemented that way when writing code. But what is actually happening under the hood is a completely different story. Correct?
    – tweekz
    Jan 19, 2023 at 19:55
0

In a language like Python, there is a lot of freedom in how to implement things like variable storage, because there is no expectation that compiled Python code can be executed with the runtime environment of a different Python implementation. That makes it possible for each implementation to make their own choices.

With the JVM, the situation is completely different. There it is the expectation that the output from any Java compiler, or any compiler that produces JVM bytecode for that matter, can be executed on any JVM implementation.

In order for that to be possible, the JVM specification must be rather strict in a number of areas to ensure the interoperability between compiler and JVM implementation.

1
  • This is false. Java and Python are at a similar level of strictness
    – user253751
    Jan 17, 2023 at 11:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.