简体   繁体   English

以非完全编译语言(例如Java)存储在堆还是堆栈中的变量?

[英]Variables stored on heap vs. stack in a non-fully compiled language (e.g. Java)?

I'm learning Java and reading how primitives (defined in methods) are stored on "the stack," vs. other things which are stored on "the heap." 我正在学习Java并阅读如何将原语(在方法中定义)存储在“堆栈”中,以及将其他内容存储在“堆”中。

But, Java is not a fully compiled to executable language, so what does it mean for things to be stored on "the stack"? 但是,Java不是完全编译为可执行语言的语言,因此将事物存储在“堆栈”中意味着什么?

I would think that the JVM would, while reading the bytecode, would have to get storage for everything using malloc/new/etc. 我认为,JVM在读取字节码时必须使用malloc / new / etc获取所有内容的存储。

Same goes for languages like Python (though I have not read anywhere that Python stores variables on stack, so no confusion for me). 像Python这样的语言也是如此(尽管我没有读过Python在堆栈上存储变量的任何地方,所以对我来说没有什么困惑)。 Since these languages are interpreted, the interpreter would, when encountering a variable definition, have to dynamically allocate memory for it, right? 由于这些语言是可解释的,因此解释器在遇到变量定义时将不得不为其动态分配内存,对吗?

The language is just an abstraction. 语言只是一种抽象。 Any implementation is allowed as long as it provides the results dictated by the language specification. 只要实现提供语言规范规定的结果,任何实现都是允许的。

When someone says that primitives are stored on the stack and objects are stored on the heap, what they really mean is that that is a natural way to implement an interpreter. 当有人说原语存储在堆栈上而对象存储在堆上时,它们真正的意思是那是实现解释器的自然方式。 In practice, you'll most likely be using a JIT, in which case objects can sometimes be stored on the stack as well. 实际上,您很可能会使用JIT,在这种情况下,有时也可以将对象存储在堆栈中。 But this is all abstracted away implementation details, so you shouldn't have to care about it. 但这都是抽象的实现细节,因此您不必关心它。 If you do, you need to find out how the particular VM you are using works. 如果这样做,则需要找出正在使用的特定VM的工作方式。

Java is not a fully compiled to executable language, so what does it mean for things to be stored on "the stack"? Java不是完全编译为可执行语言的语言,因此将事物存储在“堆栈”中意味着什么?

Not at the first step. 不在第一步。 but when you start running your Java program the JIT compiles the code into machine langauge. 但是,当您开始运行Java程序时,JIT会将代码编译为机器语言。 if not, you could not have run any Java program. 如果没有,您将无法运行任何Java程序。 any program should turn or use existing machine code in order to run. 任何程序都应打开或使用现有的机器代码才能运行。

I would think that the JVM would, while reading the bytecode, would have to get storage for everything using malloc/new/etc. 我认为,JVM在读取字节码时必须使用malloc / new / etc获取所有内容的存储。

In order to allocate data on the stack, you (usually) move the stack pointer forward or backward (depends on the stack architecture). 为了在堆栈上分配数据,您(通常)向前或向后移动堆栈指针 (取决于堆栈体系结构)。 for example on MASM syntax , in order to allocate 1 integer with the size of 4 bytes you subtract 4 bytes from the stack pointer: 例如在MASM语法上,为了分配1个4字节大小的整数,需要从堆栈指针中减去4个字节:

sub esp,4 //sub = subtract , esp = extended stack pointer

why am I telling you all this? 我为什么要告诉你这一切? because when the JIT sees something like 因为当JIT看到类似

int x; //or intermidiate language equivilant

it can transform it to 它可以将其转换为

sub esp,4

hence allocate the integer on the stack. 因此在堆栈上分配整数。

But I think I recognize where the confusion comes from. 但是我想我知道混乱的根源。
Both stack and heap allocation are done on run time 堆栈和堆分配均在运行时完成

the only exception that in C (and C++) stack allocation size is static - the size is determined on compile time , where dynamic allocation size is determined (or can be changed) on run-time. 唯一的例外是C(和C ++)堆栈的分配大小是静态的-该大小在编译时确定,而动态分配大小在运行时确定(或可以更改)。
The JIT compiles the code on run time, but it hard-code the size of the stack allocation into the assebly code, thus the size is "static". JIT在运行时编译代码,但是它将堆栈分配的大小硬编码为组合代码,因此该大小是“静态的”。

A stack is just a memory region managed in a certain way. 堆栈只是以某种方式管理的内存区域。 The specification doesn't require a particular allocation strategy, but in the end, the JVM always has to allocate the required memory in either way, regardless of whether the code to be executed has been compiled or gets interpreted. 该规范不需要特定的分配策略,但最后,JVM 总是必须以任何一种方式分配所需的内存,而不管要执行的代码是已编译还是已解释。

This isn't different to programs developed in a programming language that compiles directly to native code. 这与以直接编译为本机代码的编程语言开发的程序没有什么不同。 Programs still have to allocate memory for stacks though it may happen behind the scenes (well, in Java it also happens behind the scenes from an application programmers point of view). 程序仍然必须为堆栈分配内存,尽管它可能在后台发生(从应用程序程序员的角度来看,在Java中也可能在后台发生)。

But it seems, you have a wrong idea of the stack anyway. 但是看来,您对堆栈的想法还是有误的。 Most modern programming languages, including Java, organize a stack in frames . 包括Java在内的大多数现代编程语言都以框架形式组织堆栈。 A frame is capable of holding all local variables and the deepest operand stack that you may encounter within a method. 框架能够保存方法中可能遇到的所有局部变量和最深的操作数堆栈。 The frame for a method is allocated right at the method's entry and no further allocations are performed in the course of the execution or interpretation of the method's byte code. 方法的帧直接在方法的入口处分配,并且在执行或解释方法的字节码的过程中不执行其他分配。

Or, in other words, Java's bytecode instruction set doesn't have such a thing as a “variable definition” to process. 换句话说,Java的字节码指令集没有要处理的“变量定义”之类的东西。 There are only instructions for transferring items between the local variables (addressed by index) and the operand stack or between the operand stack and the heap. 只有指令在局部变量(由索引寻址)与操作数堆栈之间或在操作数堆栈与堆之间传输项目。 The existence of a local variable is implied by what has been written into it. 局部变量的存在暗示着已经写入了局部变量。 There are optional debugging information hinting at what variables should exist at which code location, but these information won't get processed during normal execution. 有一些可选的调试信息,提示在哪个代码位置应该存在哪些变量,但是在正常执行期间不会处理这些信息。

Depending on the JVM implementation, each thread may have a pre-allocated memory storage of a fixed maximum stack size in which stack frames get placed. 根据JVM的实现,每个线程可能具有一个固定的最大堆栈大小的预分配内存存储空间,在其中放置了堆栈帧。 In these implementations, no allocation in the sense of operating system operations is performed for the stack during the life of a thread. 在这些实现中,在线程的生存期内,不对堆栈执行操作系统操作意义上的分配。 A lot of native code follows the same model. 许多本机代码遵循相同的模型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Java ASM操作码:“H_”前缀助记符(例如Opcodes.H_GETFIELD与Opcodes.GETFIELD) - Java ASM Opcodes: “H_” prefixed mnemonics (e.g. Opcodes.H_GETFIELD vs. Opcodes.GETFIELD) 在Java Servlet中使用静态变量(例如在AppEngine中) - Usage of Static variables in Java Servlets (e.g. in AppEngine) 使用Proguard完全删除未使用的字段引用(例如,日志记录) - Fully remove unused field references (e.g. logging) with Proguard 隐藏IDE调试器中的堆栈帧(例如Java9 StackWalker) - Hide stack frames in IDE Debugger (e.g. Java9 StackWalker) C/Java 中的堆栈与堆 - Stack vs Heap in C/Java 有没有办法检查Web控制台(例如FireBug)是否以java语言打开? - Is there a way to check if web console (e.g. FireBug) is open in java language? 如何在非Java EE Web服务器(例如Tomcat)中设计JPA - How to design for JPA in a non-Java EE web server (e.g. Tomcat) 从现有变量创建一个 map(例如一个 Java 相当于 JavaScript 的`{varA, varB, varC}`) - Create a map from existing variables (e.g. a Java equivalent to JavaScript's `{varA, varB, varC}`) SQL(例如 mysql、postgresql)与 java8 流性能和更快? - SQL(e.g. mysql, postgresql) where vs java8 stream performance and faster? JAXB解析带有变量的XML文件(例如$(var1)) - JAXB Parsing an XML file with variables (e.g. $(var1) )
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM