- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
好吧,这个标题并不能理解这个想法,但基本上我的意思是在类 Base
中给定一些方法 m()
,这不是在某些子类 Derived
中重写的是当前 JVM 中的 JIT 编译器1 能够“专门化”0 m()
无论如何,当它有意义时,或者派生谁继承并且不覆盖 Base.m()
共享相同的编译代码?
这种特殊化是有道理的,派生 类定义了使 m()
更简单的东西。例如,为了便于讨论,假设 m()
调用另一个成员函数 n()
并在派生类中 n()
被定义为当 n()
被内联到 m()
时,后者被大大简化。
具体的,考虑下面类中的两个非抽象方法(都是m()
类型的方法,而抽象方法是对应的n()
方法):
public class Base {
abstract int divisor();
abstract boolean isSomethingEnabled();
int divide(int p) {
return p / divisor();
}
Object doSomething() {
if (isSomethingEnabled()) {
return slowFunction();
} else {
return null;
}
}
两者都依赖于抽象方法。假设您现在有一个像这样的 Derived
:
public class Derived extends Base {
final int divisor() {
return 2;
}
final boolean isSomethingEnabled() {
return false;
}
}
现在 divide()
和 doSomething()
方法的有效行为非常简单,divide
不是任意数字的完整除法,而是可以通过位操作完成的简单减半。 doSomething()
方法总是返回 false。我假设当 JIT
编译 divide()
或 doSomething()
时,如果 Derived
是>只有子类,一切都很好:两个抽象调用(目前)只存在一种可能的实现,CHA 将启动并内联唯一可能的实现,一切都很好。
但是,在存在其他派生类的更一般情况下,我不清楚 JVM 是否只会编译 一个2 版本的方法Base
带有对抽象方法的 invokevirtual
调用,或者如果它足够聪明地说,“嘿,即使 Derived 没有覆盖 divisor()
我应该专门为它编译一个版本,因为它会简单得多。”
当然,即使没有专门的重新编译,积极的内联通常也能正常工作(即,当您在已知的类上调用 divide()
时,甚至可能是 Derived
,无论如何,内联可能会为您提供良好的实现,但同样,在很多情况下,这种内联并未完成。
0 我的专长我不是指任何特定的东西,只是编译适用于某些受限领域的另一个版本的函数,就像说内联是一种形式专门化到特定的调用站点,或者以与大多数函数在某种程度上专门化到当前上下文(例如,加载的类、关于空性的假设等)相同的方式。
1特别是,当有人说“JVM 可以废话吗?”时一个通常是在谈论 Hotspot,我也主要在 Hotspot 中,但也在讨论其他 JVM 是否也可以做到这一点。
2好的,当然,您可能有一个函数的多个版本,用于堆栈替换、不同的编译器级别、发生去优化等...
最佳答案
Method
和 nmethod
实体之间的一对一关系可以明显看出这一点。但是,可能有多个未进入的先前版本(例如,在较低层编译的 nmethod 和 OSR stub )。此单一编译版本通常根据运行时分析针对最常见的情况进行优化。例如,在分析 Base.doSomething()
期间,JIT 发现 isSomethingEnabled()
总是在 Derived
实例上调用(即使有更多的子类),它将优化快速案例的调用,为慢速案例留下一个不常见的陷阱。优化后 doSomething()
看起来像
if (this.getClass() != Derived.class) {
uncommon_trap(); // this causes deoptimization
}
return false;
要查看方法配置文件数据,请使用 JVM 调试版本中可用的 -XX:+PrintMethodData
选项。
关于java - JVM JIT 能否专门化子类中的非覆盖方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42352282/
我想了解 Ruby 方法 methods() 是如何工作的。 我尝试使用“ruby 方法”在 Google 上搜索,但这不是我需要的。 我也看过 ruby-doc.org,但我没有找到这种方法。
Test 方法 对指定的字符串执行一个正则表达式搜索,并返回一个 Boolean 值指示是否找到匹配的模式。 object.Test(string) 参数 object 必选项。总是一个
Replace 方法 替换在正则表达式查找中找到的文本。 object.Replace(string1, string2) 参数 object 必选项。总是一个 RegExp 对象的名称。
Raise 方法 生成运行时错误 object.Raise(number, source, description, helpfile, helpcontext) 参数 object 应为
Execute 方法 对指定的字符串执行正则表达式搜索。 object.Execute(string) 参数 object 必选项。总是一个 RegExp 对象的名称。 string
Clear 方法 清除 Err 对象的所有属性设置。 object.Clear object 应为 Err 对象的名称。 说明 在错误处理后,使用 Clear 显式地清除 Err 对象。此
CopyFile 方法 将一个或多个文件从某位置复制到另一位置。 object.CopyFile source, destination[, overwrite] 参数 object 必选
Copy 方法 将指定的文件或文件夹从某位置复制到另一位置。 object.Copy destination[, overwrite] 参数 object 必选项。应为 File 或 F
Close 方法 关闭打开的 TextStream 文件。 object.Close object 应为 TextStream 对象的名称。 说明 下面例子举例说明如何使用 Close 方
BuildPath 方法 向现有路径后添加名称。 object.BuildPath(path, name) 参数 object 必选项。应为 FileSystemObject 对象的名称
GetFolder 方法 返回与指定的路径中某文件夹相应的 Folder 对象。 object.GetFolder(folderspec) 参数 object 必选项。应为 FileSy
GetFileName 方法 返回指定路径(不是指定驱动器路径部分)的最后一个文件或文件夹。 object.GetFileName(pathspec) 参数 object 必选项。应为
GetFile 方法 返回与指定路径中某文件相应的 File 对象。 object.GetFile(filespec) 参数 object 必选项。应为 FileSystemObject
GetExtensionName 方法 返回字符串,该字符串包含路径最后一个组成部分的扩展名。 object.GetExtensionName(path) 参数 object 必选项。应
GetDriveName 方法 返回包含指定路径中驱动器名的字符串。 object.GetDriveName(path) 参数 object 必选项。应为 FileSystemObjec
GetDrive 方法 返回与指定的路径中驱动器相对应的 Drive 对象。 object.GetDrive drivespec 参数 object 必选项。应为 FileSystemO
GetBaseName 方法 返回字符串,其中包含文件的基本名 (不带扩展名), 或者提供的路径说明中的文件夹。 object.GetBaseName(path) 参数 object 必
GetAbsolutePathName 方法 从提供的指定路径中返回完整且含义明确的路径。 object.GetAbsolutePathName(pathspec) 参数 object
FolderExists 方法 如果指定的文件夹存在,则返回 True;否则返回 False。 object.FolderExists(folderspec) 参数 object 必选项
FileExists 方法 如果指定的文件存在返回 True;否则返回 False。 object.FileExists(filespec) 参数 object 必选项。应为 FileS
我是一名优秀的程序员,十分优秀!