何时创建变量(内存管理)

时间:2013-12-31 22:56:31

标签: java variables memory-management reference garbage-collection

您创建一个变量来存储将来可以引用该变量的值。我听说你必须在使用它之后将变量设置为'null',这样垃圾收集器才能到达它(如果它是一个字段var)。

如果我有一个我不会引用agaon的变量,那么删除我正在使用的引用/值变量(并且只在需要时使用这些变量)可以节省内存吗?例如:

int number = 5;
public void method() {
    System.out.println(number);
}

这会占用更多空间而不仅仅是将'5'插入println方法吗?

我有一些整数,我不再在我的代码中引用(游戏循环),但我看到其他人在真正不需要它们的东西上使用引用变量。一直在研究内存管理,所以请告诉我,以及有关管理内存的任何其他建议

5 个答案:

答案 0 :(得分:5)

  

我听说你必须在使用它之后将变量设置为'null',这样垃圾收集器才能到达它(如果它是一个字段var)。

这很少是一个好主意。如果变量是对象的引用,则它只需要执行此操作,该对象的寿命比它引用的对象长得多。

假设您有一个A类实例,它有一个B类实例的引用.B类非常大,您不需要它很长时间(非常罕见的情况)您可能{{1} }引用B类以允许它被收集。

处理不能长寿的对象的更好方法是将它们保存在局部变量中。当它们超出范围时,它们会自然清理干净。

  

如果我有一个我不会引用agaon的变量,那么删除我正在使用的引用变量(并且只在需要时使用这些数字)可以节省内存吗?

在GC清理包含它的对象之前,不要释放基元的内存。

  

这会占用更多空间而不仅仅是将'5'插入println方法吗?

JIT非常聪明,可以将不变为常量的字段转换为。

  

一直在研究内存管理,所以请告诉我,以及有关管理内存的任何其他建议

使用内存分析器而不是追逐4个字节的内存。如果你有一部智能手机,那么400万字节的东西可能值得追逐。如果你有一台PC,我不会同时拥有400万字节。

答案 1 :(得分:1)

在您的示例中,number是基元,因此将存储为值。

如果您想使用引用,那么您应该使用其中一种包装类型(例如Integer

答案 2 :(得分:0)

因此注意变量在堆栈上,它们引用的值在堆上。因此,拥有变量并不是太糟糕,但是他们确实创建了对其他实体的引用。然而,在简单的情况下,你描述它并没有任何后果。如果永远不会再次读取并且在包含的范围内,编译器可能会在运行时将其删除。即使没有,垃圾收集器也能够在堆栈压扁后安全地将其删除。如果您遇到堆栈变量太多的问题,通常是因为您有很深的堆栈。每个线程所需的堆栈空间量是一个更好的调整位置,而不是使代码不可读。也不再需要null的设置

答案 3 :(得分:0)

这真的是一个意见问题。在您的示例中,System.out.println(5)会稍微提高效率,因为您只需要引用一次该数字,而不会更改它。正如在评论中所说,int是一种原始类型而不是引用 - 因此它不会占用太多空间。但是,您可能希望仅在非常复杂的方法中使用它们时才将实际引用变量设置为null。当声明它们的方法返回时,所有本地引用变量都被垃圾收集。

答案 4 :(得分:0)

好吧,JVM内存模型的工作原理如下:值存储在一堆内存堆栈中,对象存储在另一堆称为堆的内存中。垃圾收集器通过查看您已创建的对象列表并查看哪些对象未被指向任何内容来查找垃圾。这是将对象设置为null的地方;所有非原语(想到类)变量实际上都是指向堆栈上对象的引用,所以通过设置引用你必须null,垃圾收集器可以看到没有其他指向对象的东西,它可以决定垃圾收集它。 所有Java对象都存储在堆上,以便垃圾收集器可以看到和收集它们。

非原始(int s,char s,double s,这类事物)值,但不存储在堆上。它们是在需要的时候临时创建和存储的,而且你可以做的并不多,但幸好现在的编译器非常高效,并且除非绝对需要,否则将无需将它们存储在JVM堆栈上。

在字节码级别上,这基本上就是它的工作原理。 JVM基于基于堆栈的机器,还有一些指令用于在堆上创建分配对象,以及大量的操作,推送和弹出值的指令。局部变量存储在堆栈上,在堆上分配变量。*这些是我在上面提到的堆和堆栈。 Here's如果你想深入了解细节,那么这是一个非常好的起点。

在生成的编译代码中,在实现堆和堆栈方面有一些余地。分配是作为分配实现的,实际上没有办法解决这个问题。因此,虚拟机堆成为实际堆,字节码中的分配是实际内存中的分配。但是你可以在一定程度上使用堆栈,因为不是将值存储在堆栈上(并访问大量内存),你可以将它们存储在CPU上的寄存器上,这可能高达一百倍(甚至可能是比存储在内存上更快。但是有些情况下这是不可能的(查看register spilling以获取何时发生这种情况的一个示例),并且使用堆栈实现堆栈类型非常有意义。

坦率地说,在你的情况下,一些整数可能无关紧要。在这种情况下,编译器可能会自行优化它们。优化应始终在之后运行,并注意它比你喜欢它慢一点。担心先制作简单,优雅,有效的代码,然后再快速(希望)简单,优雅,有效的代码。

Java实际上做得非常好,所以你不必经常担心null变量。每当你不再需要使用某些东西时,它通常会偶然地从你的程序范围中消失(因此有资格进行垃圾收集)。所以我想这里真正的教训是尽可能多地使用局部变量。

*还有一个常量池,一个局部变量池,以及内存中的其他一些东西,但你几乎无法控制这些东西的大小,我想保持这个相当简单。