Java 什么是方法内联?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3924995/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 07:00:06  来源:igfitidea点击:

What is method inlining?

javafunctionmethods

提问by Tarik

I've been trying to understand what that really means :

我一直在试图理解这到底意味着什么:

inline function

In C++, a member function defined in the class declaration. (2) A function call that the compiler replaces with the actual code for the function. The keyword inline can be used to hint to the compiler to perform inline expansion of the body of a member or nonmember function.

inline

To replace a function call with a copy of the function's code during compilation.

内联函数

在 C++ 中,在类声明中定义的成员函数。(2) 编译器用函数的实际代码替换的函数调用。关键字 inline 可用于提示编译器执行成员或非成员函数体的内联扩展。

排队

在编译期间用函数代码的副本替换函数调用。

For example it is written something like :

例如它是这样写的:

When a method is final, it may be inlined.

当一个方法是 final 时,它可以被内联。

Here : http://www.roseindia.net/javatutorials/final_methods.shtml

这里:http: //www.roseindia.net/javatutorials/final_methods.shtml

Can you give me an example or something or basically help me to understand what "it may be inlined" means.

你能给我一个例子什么的,或者基本上帮助我理解“它可能被内联”是什么意思。

Thanks.

谢谢。

采纳答案by Tom Tresansky

Inlining is an optimization performed by the Java Just-In-Time compiler.

内联是由 Java 即时编译器执行的优化。

If you have a method:

如果你有一个方法:

public int addPlusOne(int a, int b) {
  return a + b + 1;
}

which you call like this:

你这样称呼它:

public void testAddPlusOne() {
  int v1 = addPlusOne(2, 5);
  int v2 = addPlusOne(7, 13);

  // do something with v1, v2
}

the compiler may decide to replace your function call with the body of the function, so the result would effectively look like this:

编译器可能会决定用函数体替换您的函数调用,因此结果实际上如下所示:

public void testAddPlusOne() {
  int v1 = 2 + 5 + 1;
  int v2 = 7 + 13 + 1

  // do something with v1, v2
}

The compiler does this to save the overhead of actually making a function call, which would involve pushing each parameter on to the stack.

编译器这样做是为了节省实际进行函数调用的开销,这将涉及将每个参数推入堆栈。

This can clearly only be done for non-virtual functions. Consider what would happen if the method was overriden in a sub class and the type of the object containing the method isn't known until runtime...how would the compiler know what code to copy: the base class's method body or the sub class's method body? Since all methods are virtual by default in Java, you can explicitly mark those which cannot be overriden as final(or put them into a finalclass). This will help the compiler figure out that method will never be overriden, and it is safe to inline. (Note that the compiler can sometimes make this determination for non-final methods as well.)

这显然只能用于非虚拟功能。考虑如果该方法在子类中被覆盖并且包含该方法的对象的类型直到运行时才知道会发生什么......编译器如何知道要复制什么代码:基类的方法体或子类的方法体方法体?由于所有方法在 Java 中默认都是虚拟的,您可以显式标记那些不能被覆盖的方法final(或将它们放入一个final类中)。这将帮助编译器确定该方法永远不会被覆盖,并且内联是安全的。(请注意,编译器有时也可以为非最终方法做出此决定。)

Also, note the word mayin the quote. Final methods aren't guaranteed to be inlineable. There are various ways you can guarantee a method isn't capable of being inlined, but no way to forcethe compiler to inline. It will almost always know better than you anyway when inlining will help vs. hurt the speed of the resulting code.

另外,请注意引号中的单词可能。不保证最终方法是可内联的。有多种方法可以保证方法无法内联,但无法强制编译器内联。无论如何,它几乎总是比您更了解内联将有助于还是损害结果代码的速度。

See wikipediafor a good overview of benefits and problems.

有关好处和问题的完整概述,请参阅维基百科

回答by aioobe

Let's say you have a class that looks like this:

假设您有一个如下所示的类:

public class Demo {
    public void method() {
        // call printMessage
        printMessage();
    }

    public void printMessage() {
        System.out.println("Hello World");
    }
}

The call to printMessagecould be "inlined" in the following way:

printMessage可以通过以下方式“内联”调用:

public class Demo {
    public void method() {
        // call printMessage
        System.out.println("Hello World"); // <-- inlined
    }

    public void printMessage() {
        System.out.println("Hello World");
    }
}

(This is actually not done on the level of Java (not even on bytecode level) but during JIT-compilation, but the example above illustrates the concept of inlining.)

(这实际上不是在 Java 级别(甚至不是字节码级别)完成的,而是在 JIT 编译期间完成的,但上面的示例说明了内联的概念。)

Now consider what would happen if the printMessagemethod was overloaded by another class, like this:

现在考虑如果该printMessage方法被另一个类重载会发生什么,如下所示:

class SubDemo extends Demo {
    public void printMessage() {
        System.out.println("Something else");
    }
}

Now if the compiler inlined the call to Demo.printMessageit would be stuck with System.out.println("Hello World");which would be wrongin case the object was actually an instance of SubDemo.

现在,如果编译器内联调用Demo.printMessage它会坚持使用System.out.println("Hello World");这将是错误的情况下,对象竟是一个实例SubDemo

However, if the method was declared finalthis would not under any circumstances be the case. If the method is "final" it means that it can never be overridden with a new definition, thus, it is safe to inline it!

但是,如果声明了final该方法,则在任何情况下都不会出现这种情况。如果该方法是“final”,则意味着它永远不会被新定义覆盖,因此,内联它是安全的!

回答by Chris Judge

Calling a function is not free. The machine must maintain a stack frame so that it can return to the calling section of code when the called function is complete. Maintaining the stack (including passing function parameters on this stack) takes time.

调用函数不是免费的。机器必须维护一个堆栈帧,以便在被调用的函数完成时它可以返回到代码的调用部分。维护堆栈(包括在此堆栈上传递函数参数)需要时间。

When a function is in-lined, the compiler replaces the call to the function with the function's code so that one can avoid the performance penalty of a function call at run-time. This is one of the classic trade-offs in programming: the run-time code gets a little bigger (takes up more memory), but it runs a little faster.

当一个函数被内联时,编译器用函数的代码替换对函数的调用,这样就可以避免在运行时函数调用的性能损失。这是编程中的经典权衡之一:运行时代码变得更大(占用更多内存),但运行速度更快。