当我在某处读到时,在创建实例并从堆分配空间时分配内存。如果它是正确的,那么在实例和对象创建期间分配了多少内存?
答案 0 :(得分:7)
方法中声明的变量存储在堆栈中,而实际对象存储在堆中。考虑
Integer a = new Integer(10);
在此示例中,在堆上创建Integer类型的对象,并返回引用(32或64位)并将其作为变量' a'存储在方法堆栈中。如果JVM更喜欢优化,JVM可以自由地将这样的变量保存在CPU寄存器中。
使用new关键字时会分配对象的内存。它通常在TLAB(线程本地分配缓冲区)内分配,它是正在运行的线程保留的eden heap的一部分。从而将对象分配的开销减少到一个简单的指针碰撞'。不使用TLAB时的两次是1)当对象对于剩余的空间来说太大时,在这种情况下,当支持JVM决定通过{{3时,它将被直接提升到old gen和2)它可以完全避免对象并直接分配到堆栈上(甚至可以将对象分开并只分配堆栈中所需的字段)。
保留的内存量包括一个对象头,通常为2 escape analysis(数组为3),然后是对象及其父类中声明的每个字段的空间。这些字段的总大小取决于JVM和底层平台(例如32位或64位)和JVM配置(如压缩引用)。
------------------+------------------+------------------ +--------------------------
| mark word | klass pointer | array size (opt) | padding and fields |
------------------+------------------+-------------------+--------------------------
要求JVM提供尺寸不受官方支持,但words是一个非常好的最佳猜测'它使用不同JVM的知识并通过EHCache sizeOf访问底层指针。
理解每个字段大小的起始位置是Java Unsafe,但这只是最小的大小,因为JVM设计为使用32位,因此小于此的基元通常被填充到32位。例如布尔人。
字段的确切布局将因JVM而异,但它们将倾向于按照从继承树的根开始定义它们的类进行分组。例如,考虑
和
上面的图片是从非常好的size of primitives defined by the Java language中拍摄的,它很好地描述了内存布局,
答案 1 :(得分:2)
"创建实例"与&#34具有相同的含义;使用new
创建新对象"。
在正常情况下,堆内存将在您请求new
对象时分配,但这不是一成不变的:HotSpot还可以确定在调用时分配对象是安全的堆栈(通过逃逸分析的过程)。这样更有效,因为它不需要任何垃圾收集。
分配了多少内存是高度特定于实现的,只保证Java数组被打包" (模数固定的开销)。但是,布尔数组被指定为每个元素占用一个字节。
答案 2 :(得分:1)
正如我在某处读到的那样,在创建实例并从堆中分配空间时分配内存。
是的,你是对的,除非new
被调用,否则它只是一个指向任何内容的null
引用。
如果它是正确的,那么在创建实例和对象的时候分配了多少内存?
取决于对象的大小。
请查看Primitive Data Types以了解他们的身材。
答案 3 :(得分:1)
我正在阅读你的问题:“谁为对象实际分配内存 - new
关键字或构造函数?”如果是这种情况,答案是{{ 1}}关键字。
构造函数通常是链接的,这意味着在创建实例时至少会运行两个构造函数。另一方面,实例的内存仅分配一次。
此外,分配的类型是使用所产生的参考的使用分析来确定的(例如,逃逸分析)。这意味着发生分配的最明显的地方是构造函数调用站点(即new
表达式的位置)。
分配的内存大小使得它可以容纳new
关键字后面的类型实例。后一个大小(类型实例的大小)是
new
,int
,float
等)由在任何情况下,当您执行double
时,其中T obj1 = new T()
是类的名称:
T
实例。T
变量中。执行obj1
时,R obj2 = new R()
类型会发生类似情况,类型R
的大小可能与R
不同。
但这些局部变量都不包含实例。它们都包含对其指定对象的引用。 (因此,变量本身甚至可能具有相同的大小,如果他们只需要存储一个内存地址。)
答案 4 :(得分:0)
类变量
当从同一个类蓝图创建多个对象时,它们每个都有自己不同的实例变量副本。在Bicycle类的情况下,实例变量是节奏,齿轮和速度。每个Bicycle对象都有自己的这些变量值,存储在不同的内存位置。
有时,您希望拥有所有对象共有的变量。这是通过静态修改器完成的。在声明中具有static修饰符的字段称为静态字段或类变量。它们与类相关联,而不是与任何对象相关联。该类的每个实例共享一个类变量,该变量位于内存中的一个固定位置。任何对象都可以更改类变量的值,但也可以在不创建类实例的情况下操作类变量。
https://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html