首先,为什么C ++的汇编速度比Java慢?运行程序有什么区别?了解Java的早期和晚期过程后,您可以理解此问题。
这里将有15个问题来确认它是否真正理解。如果根本没有概念,请仔细查看本文末尾的“ JVM汇编优化说明”一章。
问:Java的早期汇编过程是哪个3?a ::
1.分析单词和语法符号的符号
2.评论处理
3.语义分析和字节码生成。
问:在上面的步骤中,什么是符号表?a:符号表是由符号地址和符号信息组成的表。
问:注释处理器做什么?a:注释处理器将在抽象语法树中扫描带有注释的元素并更新语法树。要点是,他是根据语法树进行更新的。回到分析,填充和重新处理的过程。
问:在上述三个步骤中,解决方案是哪个步骤?A:第三步是仅在生成字节代码时处理语法糖。
问:什么是语法糖?可能是什么?a ::
问:生成字节代码类文件时,最终和非最终条件的本地变量会不同吗?a:没有差异。本地变量不会在常数池中引用,因此不会有ACESSSES_FLASG信息。*因此,最终的本地变量在运行时没有任何效果,并且仅在编译期间进行验证。**
问:a = 1 + 2的哪个阶段优化?a:在对早期编译过程的语义分析期间,执行恒定折叠以变为a = 3。字符串 +数字被优化为StringBuilder.Append()。该动作在此阶段还进行了优化。
问:加载对象的过程有一堆序列
答:字节码反映在字节代码中。
问:早期汇编与优化和晚期汇编优化之间的差异?a ::
问:当Java程序运行时,它是否直接变成了优化的机器代码,然后运行?A:错误。
请注意,此处的编译器与前面提到的编译器之间的差异是一个编译为字节代码,另一个编译为机器代码。
问:有两个高级优化编译器
它们有什么区别?
A::
C1编译器,较高的编译速度,通常编译的质量。
C2编译器,更好的编译质量,但速度缓慢。
C1编译器是优化的操作,无需运行即可进行优化。
C2编译器将根据解释器提供的监视信息执行激进而动态的优化
问:如何区分Java中的C1或C2?A:关于这两个编译器的参数:
在混合模式下,JDK7引入了分层编译策略:第0号:说明执行。请勿打开性能监视。Layer1:C1编译,将字节代码编译为本地代码,执行一些简单的优化,添加性能监视层2:C2编译,启动-up时间 - 耗费优化,根据性能监控信息执行自由基优化信息
问:在分层优化中,如果您正在运行,JVM如何知道要优化JIT或OSR的代码?A ::
1.多次被调用的方法。将触发JIT编译(热代码计数器)
2.多次执行的周期将触发OSR汇编(在堆栈上更换),该汇编发生在方法执行过程中,因此将其编译并切换在堆栈上。(使用边框计数器)
问:早期优化将使用哪些方法,以及以后的优化中将使用哪些方法?a ::
问:Java数组通常会自动执行边界检查。如果不满足,它将是abnormal的。在什么情况下将优化此自动检查?A:在运行时,当在数组中找到传球的参数时,它绝对不会超过边界,并且会优化此检查行动。
阅读上述内容后,您可以给出C ++和Java汇编和操作速度差距之间差异的原因:
1. Java即时汇编可能会影响用户体验,如果操作过程中造成巨大影响的延迟。
2. Java中的虚拟方法比C ++更多,因为各种内部关节分析消耗的检查和优化越多,越大,
3. Java总是进行安全检查。如果您不在C ++中这样做,那么当我犯了一个错误时,我直接折叠了交叉订单。
4.C ++内存释放允许用户控制它,而无需在后台获得垃圾回收器,始终检查和操作
5. Java好处:可以在运行时通过性能监控来优化即时编译。这就是C ++无法完成的
汇编过程大致分为三类:
1.分析并填充符号表
2.评论处理
3.分析和字节码生成
关键点:
上述步骤的详细说明:
第一步:
-------词汇分析:
代码转换为令牌标记。例如,int a = b+2转到int a = b+2。
-------语法分析(请注意,它实际上仅生成语法树,而无语法验证):
基于生成的令牌,构建了一个抽象的语法树。
-------填充符号表:
生成一个符号地址和符号信息表。(以下步骤的第三步将用于语义分析中的标签检查。例如,该名称的使用是否与描述一致,还将用于生成中间代码。
第2步:
-------注释处理器:
注释处理器将用抽象语法树中的注释扫描元素并更新语法树。更新后,我们将返回分析,填充和重新处理的过程。此处理器是插件-in,我们,我们可以继续自己添加。
请注意,上面的两个步骤只是在转换源文件,并且不涉及任何与语法相关的规则。
第三步:
-------语义分析:
确定语法树是否正确。分为两种类型:
1.标记检查:检查变量是否已声明,分配和等效的数据类型在标签检查过程中与恒定折叠匹配,并将a = 1+2折叠成3标签检查范围。
2.数据和控制流分析过程上下文的逻辑进一步验证,此处将涉及许多交互式上下文上下文和依赖性,例如退货价值方法是否包含回报在使用局部变量之前,请使用局部变量。
最终的本地变量(或最终参数)和非最终局部变量没有什么不同。由于本地变量在常数池中不保存符号引用,因此不会有acessses_flasg信息。因此,类文件不知道本地变量是否不知道是最终的,因此最终的本地部分对运行期没有影响,并且只会在编译期间进行验证。
-------解决语法糖果:
虚拟机本身不支持这种语法,但是在编译阶段,它将这些语法糖转换为通用的语法结构(换句话说,语法糖果代码已转换为普通代码,例如自动包装和拳击,这些代码已将其转换为普通的代码可以将转换器转换为转换器。包装方法的具体调用)
-------字节代码生成:
对象的初始化顺序实际上将在字节代码生成阶段中收敛为一种方法,也就是说,在INIT控件中,成员的排序顺序和构造方法是相同的。它还收敛到PS:请注意,默认构造函数已在符号表阶段完成。最终符号表将移交给ClassWrite类。设计概念将来自字节码和文件
在Hotspot中,解释器与编译器共存。当该程序刚刚启动时,它将使用解释器立即扮演角色。在程序运行后,编译器逐渐扮演角色并逐渐编译未使用的代码。在相对较小的内存资源中,您可以使用解释器运行程序来减少编译文件。如果编译器的优化出现错误,则可以通过“反向优化”来运行回到初始解释器模式。
口译员插座
翻译
有两个编译器
当您选择-client或-server时,将使用它。
关于这两个编译器的参数:
在混合模式下,解释器需要收集绩效信息,并为汇编阶段提供判断和优化。此绩效信息有些浪费。因此,JDK7引入了分层汇编策略:
CC和SC汇编过程之间的差异:
前字节代码 - “方法内部联盟/常数通信(基本优化) - ” HIR(高级中间代码) - “价值检查和消除/范围检查并消除
- “后端将HIR转换为LLR(低级中间代码) - “线性扫描算法分配寄存器 - ” Swaning Pole Polet优化 - “机器代码Genesis-”本地代码生成
这是一些可以优化的操作,而无需运行信息周期
将执行所有经典优化动作
无线电优化将根据CC或口译员提供的监视信息进行优化
寄存器发行器是全局图颜色分布
----热代码
1.多次被调用的方法。将触发JIT汇编
2.多次执行的周期将触发OSR汇编(在堆栈上替换),该汇编发生在方法执行过程中,因此将其编译并切换在堆栈上。
热点使用计数器的热点检测方法来确定热代码。*为每种方法创建一个方法计数器。如果在周期内超过阈值,则将触发JIT编译和替换方法入口。在解释方法中的字节码内容的刚度。
计数器-XX的相关参数: - userCounterDecay关闭热衰减-XX:countrafimeTime设置半寿命-XX:compilethreshrond设置方法以编译阈值编译阈值
后边计数器是计算循环数的计数器。*它将溢出并调整方法计数器到溢出。* OSR比率,server = CompileThredShold *(OSR比率-Interpreter监视比率)
- 冗余访问消除:
如果获得了A.值,则A.值将不会在此方法中更改,则该值将不会从随后的值使用中获取:
变得
无用的代码消除:删除上述y = y
----公共亚表达消除
它是要使一些长的计算公式A+(A+B)2_将尽可能优化为A_3+B*2,以减少计算数量
- 精英边境检查:
如果您可以确定特定循环中的数组中的数组不会超过数组范围,则[]值操作将不会执行数组边界检查。
- Mino -Type异常处理:
if(a == null){xxx} else {throw exception}优化以尝试{xxx} catch(异常e){throw e}
----方法内联邦:
不能重写的方法,例如私有,构造函数,静态和其他方法,可以直接在早期优化中进行优化。
将实现的其他方法抽象继承不能在编译器中使用,因为他不知道其实际使用的代码部分。
----逃脱分析:
分析新的对象是否不会逃脱到该方法中。如果已确认它仅在方法中使用,则没有人会在外面引用他,然后将其优化。在方法堆栈中,该方法直接终止对象。*无需锁定该对象,然后同时锁定该对象操作*结算替换:作为局部变量,该对象中最小的基本类型成员的拆除。
---- Java和C ++,即时编译和静态汇编之间的差异:
1.即时汇编可能会影响用户体验。
2. Java中的虚拟方法比C ++更多,因为各种内部关节分析消耗的检查和优化越多,越大,
3. Java必须始终进行安全检查。如果您不在C ++中这样做,我直接折叠了交叉订单。4.C ++内存发布允许用户控制它。无需在后台获得垃圾回收器来检查和操作5.Java好处:可以通过在性能期间进行监视来优化即时汇编。这就是C ++无法完成的操作。
作者:BreakDraw。
