I know this is JVM dependent and every virtual machine would choose to implement it a little bit different yet I want to understand the overall concept.
It has been said that for the Memory Segments that the JVM uses to execute a Java program
Java Stacks
Heap
Method Area
PC Registers
Native Method Stacks
are not necessarily implemented with contiguous memory and may be all actually allocated on some heap memory provided from the OS, this leads me to my question.
JVM's that fully use the JIT mechanism and compiles bytecode methods
into native machinecode methods store these methods somewhere, where
would that be? the execution engine ( that is usually written in C /
C++ ) would have to invoke these JIT compiled functions, yet the kernel shouldn't allow a program to execute code saved on the stack / heap / static memory segment, how could the JVM overcome this?
Another question I have is regarding the Java stacks, when a method ( after JIT compilation ) is executed within the processor it's local variables should be saved within the Java stacks, yet again the Java stacks may be implemented with a non-contiguous memory and perhaps even just some stack data structure allocated on the heap acting as a stack, how and where do the local variables of a method being executed get saved? the kernel shouldn't allow a program to treat a heap allocated memory as a process stack, how does JVM overcome this difficuly as well?
Again, I want to emphasis that I'm asking for an overall concept, I know each JVM would choose to implement this a little bit different...
JVM's that fully use the JIT mechanism and compiles bytecode methods into native machinecode methods store these methods somewhere, where would that be?
It is stored in the "Perm Gen" in Java <= 7 and "meta space" in Java 8. This is another native memory region.
the execution engine ( that is usually written in C / C++ ) would have to invoke these JIT compiled functions, yet the kernel shouldn't allow a program to execute code saved on the stack / heap / static memory segment, how could the JVM overcome this?
The memory region is both writable and executable, though I don't know exactly which system call is required to implement this.
Another question I have is regarding the Java stacks, when a method ( after JIT compilation )
Initially the code is not compiled but it uses the stack in the same way.
is executed within the processor it's local variables should be saved within the Java stacks, yet again the Java stacks may be implemented with a non-contiguous memory
There is a stack per thread which is continuous.
and perhaps even just some stack data structure allocated on the heap acting as a stack, how and where do the local variables of a method being executed get saved?
On the thread stack.
the kernel shouldn't allow a program to treat a heap allocated memory as a process stack, how does JVM overcome this difficuly as well?
It doesn't do this.
Related
Every time when I initiate a list in java, I will do
List<Integer> list = new LinkedList<>();
I assume that this will allocate the list on heap. Wonder if there's anyway that I could allocate the list on stack?
All objects, including their individual attributes, are stored on the heap.
All local variables, and their arguments, are stored on the stack because they contain primitive values or references.
However, in special cases, the java virtual machine may perform escape analysis and decide to allocate objects (including your LinkedList) on a stack, but this normally doesn't happen and isn't a major concern.
As a general rule, if you allocate an object on a stack you will get a copy of the object when you call a function that refers to it. In contrast, if you allocate an object on the heap, when you pass the pointer to the object you will get a copy of the pointer (which points to the very same object on the heap.)
It is theoretically possible for JVM implementations to allocate objects on the stack, using "escape analysis." If it can be determined that a reference to a created object never leaks off the stack, a JVM could allocate it on the stack instead of the heap. The benefit of this would be to reduce garbage collection overhead; when the stack frame is exited, that memory could be immediately reclaimed. It might also boost speed because of the locality of reference.
Starting in Java 7, escape analysis was introduced in the Oracle's HotSpot Java runtime. With this enhancement, HotSpot may choose not to allocate stack-local objects that aren't modified; rather than allocating them on the stack, it deletes the allocation altogether. While this stops short of stack allocation, it does demonstrate that such things are permissible runtime optimizations.
There is no way for the Java programmer to directly control this behavior, however. It's an optimization performed by the JIT compiler. I'm not sure if the language specification would permit this sort of optimization at compile-time. It might, but I haven't studied it.
I am currently reading the last specification of the JVM. It is clear that each thread has its own call stack and its own program counter that keeps track of the (next) instruction to execute.
My question is maybe dump, but from the description, I cannot find an answer.
Where is the current program counter stored when a new or a method is invoked?
In other terms, how does the thread now where to continue after the invokation of a method?
The answer is implementation-dependent as different hardware architectures and even different JVMs may implement this behavior in different ways. In the standard Oracle JVM, most of your bytecode will be compiled to native code by JIT (Just in Time compiler) and method calls will be executed as for native code (give or take some extra code which may be added to handle checkpointing etc.). On a PC this means that current register values, including the instruction pointer / program counter will be saved on the stack before a method call. When returning from the call, the processor pops these values from the stack, among them the return address.
I came to doubt after doing this.
I had created a DLL in which APIs accepts pointers to some values from application. I am able to access those pointers in DLL.
So i had a doubt how is memory allocated for functions present in DLL and called from application. It should occur in calling proccess memory space.
Am i right?
You are right: DLL and application shares the same address space, so at system level the is no problem of allocated memory usage.
But you must be careful with deallocation of memory, which was allocated by code from another module. It will work correctly only if:
Both modules are built on the same platform (e.g. Visual C++).
Both modules use the same heap manager from the third shared DLL (e.g. msvcrt).
I am using Keil's ARM-MDK 4.11. I have a statically allocated block of memory that is used only at startup. It is used before the scheduler is initialised and due to the way RL-RTX takes control of the heap-management, cannot be dynamically allocated (else subsequent allocations after the scheduler starts cause a hard-fault).
I would like to add this static block as a free-block to the system heap after the scheduler is initialised. It would seem that __Heap_ProvideMemory() might provide the answer, this is called during initialisation to create the initial heap. However that would require knowledge of the heap descriptor address, and I can find no documented method of obtaining that.
Any ideas?
I have raised a support request with ARM/Keil for this, but they are more interested in questioning why I would want to do this, and offering alternative solutions. I am well aware of the alternatives, but in this case if this could be done it would be the cleanest solution.
We use the Rowley Crossworks compiler but had a similar issue - the heap was being set up in the compiler CRT startup code. Unfortunately the SDRAM wasn't initialised till the start of main() and so the heap wasn't set up properly. I worked around it by reinitialising the heap at the start of main(), after the SDRAM was initialised.
I looked at the assembler code that the compiler uses at startup to work out the structure - it wasn't hard. Subsequently I have also obtained the malloc/free source code from Rowley - perhaps you could ask Keil for their version?
One method I've used is to incorporate my own simple heap routines and take over the malloc()/calloc()/free() functions from the library.
The simple, custom heap routines had an interface that allowed adding blocks of memory to the heap.
The drawback to this (at least in my case) was that the custom heap routines were far less sophisticated than the built-in library routines and were probably more prone to fragmentation than the built-in routines. That wasn't a serious issue in that particular application. If you want the capabilities of the built-in library routines, you could probably have your malloc() defer to the built-in heap routines until it returns a failure, then try to allocate from your custom heap.
Another drawback is that I found it much more painful to make sure the custom routines were bug-free than I thought it would be at first glance, even though I wasn't trying to do anything too fancy (just a simple list of free blocks that could be split on allocation and coalesced when freed).
The one benefit to this technique is that it's pretty portable (as long as your custom routines are portable) and doesn't break if the toolchain changes it's internals. The only part that requires porting is taking over the malloc()/free() interface and making sure you get initialized early enough.
Consider an case that I have to call C++ code from my Java Program. The C++ code creates thousands of Objects. Where are these dynamic objects stored ? I suspect in the JVM heap because the native code will be a part of the same process as the JVM.
If yes, do the rules of Java Garbage collector thread apply on Objects of the C++ code ?
For the first question, C++ will allocate resources using its own runtime which has nothing to do with the JVM - the JVM is not aware of any activity in this memory allocator.
For the second question, the Java garbage collector will not GC the memory allocated by C++. You will have to make sure that your Java wrapper initiates the memory release. Before an object is GC'd by java, the runtime calls the finalize() method. The default one is inherited from java.lang.Object and basically does nothing. You can override this and use it as a hook to initiate deallocating your manually managed memory.