简体   繁体   English

Java销毁变量

[英]Java Destruction of Variables

I was asked this by a fellow developer recently, and could not provide the answer... 最近有一位开发人员问我这个问题,但无法提供答案...

In Java, how/when are variables disposed of? 在Java中,如何/何时处置变量? Are they? 是吗

Let's say we have a run() method that gets called 50-75 times per second (heavily simplified example)... 假设我们有一个run()方法,每秒调用50-75次(非常简化的示例)...

public void run() {
    long lastTime = System.nanoTime();
    double unprocessed = 0;
    int ticks = 0;
    int frames = 0;
    double nsPerTick = 1000000000.0 / 60.0;
    long now = System.nanoTime();
    unprocessed += (now - lastTime) / nsPerTick;
    lastTime = now;

    ticks++;
    tick();
    unprocessed -= 1;
}

Would bringing those variables (lastTime, unprocessed, ticks, etc.) into a higher level of scope make the program run better/more efficiently--to a place where they are not created and used multiple times per second? 将这些变量(lastTime,未处理,滴答声等)带入更高的范围会否使程序更好/更有效地运行-到每秒不会创建和使用多次的地方?

It won't give you any performance improvement as those variables are created in stack . 由于这些变量是在stack中创建的,因此不会给您带来任何性能改进。

Read this article to get more about Object destructions in Java: 阅读本文以获得有关Java中对象销毁的更多信息:

What method in Java is used to destroy your objects Java中使用哪种方法销毁对象

Java uses a garbage collector , so unused objects are disposed of automatically. Java使用垃圾回收器 ,因此未使用的对象将被自动处理。 In your example you use only local variables, they are allocated on the stack and this is very fast (and no garbage collection is involved here). 在您的示例中,您仅使用局部变量,它们在堆栈中分配,并且速度非常快(这里不涉及垃圾收集)。 Moving these variables to the outer function ("higher in the scope") would not help. 将这些变量移至外部函数(“范围较高”)将无济于事。

In Java, how/when are variables disposed of? 在Java中,如何/何时处置变量? Are they? 是吗

First, lets get something clear. 首先,让我们弄清楚。 In Java, there are things called variables, and there are things called objects. 在Java中,有些东西叫做变量,有些东西叫做对象。 Variables and objects are not the same thing. 变量和对象不是一回事。

A variable in Java is always part of something else: Java中的变量始终是其他内容的一部分:

  • An local variable is part of the state of a method call . 局部变量是方法调用状态的一部分。 It gets disposed of when it goes out of scope. 超出范围时将被丢弃。 That typically means when the method call ends and the method call's stack frame gets popped from the call stack. 通常意味着方法调用结束并且方法调用的堆栈框架从调用堆栈弹出。

  • An instance variable (or field or attribute) is part of an object. 实例变量(或字段或属性)是对象的一部分。 It gets disposed of when the object gets disposed of. 当对象被丢弃时,它将被丢弃。

  • A static variable (or class variable) is part of a class, and will only get disposed of if the class is unloaded. 静态变量(或类变量)是一类的一部分,并且将仅获得设置如果类被卸载的。

In your example, all of the variables are local variables, and will be "disposed of" when the current call to the run() method returns (or terminates due to an exception). 在您的示例中,所有变量都是局部变量,并且在对run()方法的当前调用返回(或由于异常而终止run()时将被“处置”。

Would bringing those variables (lastTime, unprocessed, ticks, etc.) into a higher level of scope make the program run better/more efficiently--to a place where they are not created and used multiple times per second? 将这些变量(lastTime,未处理,滴答声等)带入更高的范围会否使程序更好/更有效地运行-到每秒不会创建和使用多次的地方?

It wouldn't help. 这没有帮助。 The incremental cost of creating or disposing of a local variable is ZERO 1 . 创建或局部变量的处置的增量成本是零1。 And the cost of using a local variable is (if anything) less that the cost of using an instance variable. 并且使用局部变量的成本(如果有的话) 使用实例变量的成本要低。 The only cost might be in initializing it, but you would incur that cost anyway; 唯一的成本可能是初始化它,但是无论如何,您都会产生该成本。 eg in re-initializing an instance variable on each method call. 例如,在每个方法调用上重新初始化实例变量。

Indeed, turning local variables into instance variables could actually be a bad thing. 事实上,把局部变量为实例变量实际上可能是一件坏事。 It would mean that the method now uses object variables to represent its state, making it non-reentrant. 这意味着该方法现在使用对象变量来表示其状态,从而使其不可重入。 (It is unclear whether that matters here. It depends on whether the run() method is used in a way that requires it to be reentrant ... and typically that is not the case.) (目前尚不清楚这是否重要。这取决于是否以可重入的方式使用run()方法……通常情况并非如此。)


1 - That's slightly over-simplified. 1-有点过分简化了。 If you have a large enough number of local variables and/or a deeply recursive method, then it is possible that you will need to use a larger-than-normal thread stack size. 如果您有足够多的局部变量和/或深度递归的方法,则可能需要使用比正常线程堆栈大的大小。 That extra memory usage would be a cost. 那额外的内存使用将是一个代价。

The answer to this question depends on Java's Garbage collection which is having a smaller slice called as "nursery gc" which gets invoked very frequently and does not cause jvm halt. 这个问题的答案取决于Java的Garbage集合,该集合具有一个较小的切片,称为“ nursery gc”,该切片被频繁调用且不会导致jvm停止。 all the local variables goes to this nursery gc. 所有局部变量都转到该托儿所gc。 When this method execution finishes; 该方法执行完成时; all these variables are eligible for GC; 所有这些变量都符合GC条件; and are removed when nursery gc is invoked. 并在调用托儿所gc时将其删除。

Answering your question whether moving these variables out of run method be better. 回答您的问题是否将这些变量移出运行方法会更好。 Though JVM is getting smarter with every release; 尽管JVM在每个发行版中都变得越来越聪明。 creation of objects is less impact on performance. 创建对象对性能的影响较小。 But still I feel even with that minimal impact; 但是我仍然感到即使影响很小。 I feel there is no harm in making objects global. 我觉得使对象具有全局性没有害处。

Though in this case all the variables are primitive; 尽管在这种情况下,所有变量都是原始变量。 it will not create any impact. 它不会产生任何影响。

Id depends on JVM run mode, and JVM version. ID取决于JVM运行模式和JVM版本。

But most JVM version will perform like this: 但是大多数JVM版本将执行以下操作:

When JVM run on -client mode the code will run line by line. 当JVM在-client模式下运行时,代码将逐行运行。

But when JVM run on -server mode, code will be optimize: 但是,当JVM在-server模式下运行时,代码将被优化:

Suppose the tick() method is: 假设tick()方法为:

public void tick(){
   System.out.println("tick");
}

Final code after optimize maybe: 优化后的最终代码可能是:

public void run() {
  long lastTime = System.nanoTime();
  int ticks = 0;
  int frames = 1;
  double unprocessed = (System.nanoTime() - lastTime) / 16666666.66 -1 ;
  // tick method will inline here instead of invoking tick();
  System.out.println("tick");
}

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM