It is NOT the case that every INSTANCE has it's own static segment.
Every CLASS has its own static segment that is accessible by any constructor, function, or method of that class.
A static variable belong to the CLASS and is stored in THAT class' static segment, so their values are not only accessible by that class's subroutines (constructors, functions, and methods), but any change made to a static variable persists and is then visible to other calls to one of that class's subroutines.
A field variable belongs to a particular INSTANCE of a class and is only visible to the constructors and methods of that class -- functions are not associated with a specific instance and therefore have no way to even know which instance's field variables it should be accessing.
The local and parameter variables are local variables specific to each call of each subroutine (the kind of subroutine doesn't matter).
If you have a declaration
static Array heap;
then you have a SINGLE variable in the static segment named "heap" and the value stored in that single variable is a reference to (i.e., the address in RAM of) an object of type Array that has been (or will be) created using a constructor for the Array class.
To add to this, remember that a static variable is common to (shared among) all the instances (or objects) of the class because it is a class level variable. Static variables are used when only one copy of the variable is required.
Whereas a field is specific to a single instance of a class. You might have a "Person" class with fields such as age and height. Age and height are fields because you want every instance of the Person class to store its own age and height. Imagine an Array or linked list (or whatever data structure) of 1,000 Persons, each with their own age and height. Age and height are fields.
The Person class might define a static variable that any Person instance (or function) can access. But a static variable is a class level variable, stored only once, to be shared by all 1,000 Persons. You can think of it as sort of a global variable, although it's at the class level. Other classes cannot see them. One example might be a total count of all Persons created - the Person class could track that in a single static variable. Another example might be as a constant used by other functions in the class.
That is correct. The "other classes cannot see them" is true in the sense that they cannot see them using Jack syntax. But any Jack program has access to all the memory, so if it knows which address the compiler assigned them to, they can read or even modify them.
yes, RAM - RAM will store all the static variables for all the classes in your compiled project. But a Jack programmer would usually ignore this fact. Many Jack programmers wouldn't even know about those RAM locations because they don't have to know. What if someone had written a VM translator for a different machine (not the Hack machine)? Then those RAM addresses would be bogus.
Rather than poking around in memory, if you really want a class you write in Jack to externally expose a static variable for reading or writing, then you would provide functions or methods in your class that do that. That way you have a formalized API, and the class knows best how to read and write its own static variables.
Of course, classes do this all the time with their own field variables, too (though in that case it would have to be a method, not a function).
But the static variables are stored on the static segment, and each class have its own part of the static segment, e.g. Class1 uses RAM 16 to 18, Class2 uses RAM 19 to 21.
In that sense, we can peek/poke any static variables, of any class, on the static segment.
Is this right ?
Yes and no.
In theory, you can use Memory.peek() and Memory.poke() to access any RAM location in memory. Some tools, such as the VM Emulator, make this difficult in some instances because it believes that the THIS and THAT pointers should never point to memory outside of the Heap or Screen segments and will crash if you try to use them this way, so you have to play games that you really shouldn't in order to access arbitrary RAM locations below 2048.
But even if that's not the case, you have the problem of knowing what the mapping is between the Jack program's static variables and the RAM. For instance, let's say that the first Fred.vm file to be translated (which may or may not correspond to the first Jack class to be compiled) has three static variables that are used. These will get called something like Fred.static.0, Fred.static.1, and Fred.static.2 and these will, collectively, get mapped onto RAM, RAM, and RAM. But if the first use of one of these three static variables is Fred.static.2, that it will get mapped to RAM, and so on.