当前位置: 主页 > JAVA语言

java代码编译-java代码编译

发布时间:2023-03-24 09:16   浏览次数:次   作者:佚名

java代码编译_java代码编译_java eclipse 编译

编译线程

当达到编译阈值时,方法或循环就是进入编译队列,在后台异步地获取队列的代码进行编译。

编译队列不是严格的先进先出,执行次数越多的代码具有更高的优先级。这也是在上一章节,我们通过标志PrintCompilation查看被编译方法时,compilationg_id不完全按顺序递增的原因。

使用不同的编译器,在不同平台下会有不同的线程数,与平台的cpu数有关。

通常来说,使用client编译器,则会开启一个线程;使用server编译器,则会开启两个线程。当开启分层编译时,将会开启多个线程,在不同的平台的CPU数量下,线程数也会不同,在分层编译器中,会将client编译器称为C1编译器,将server编译器称为C2编译器,我们下满就这么称呼它们java代码编译,简单列举几个情况:

cpu数量

C1

C2

1

1

java代码编译_java eclipse 编译_java代码编译

1

2

1

1

4

1

2

8

1

java eclipse 编译_java代码编译_java代码编译

2

16

2

6

32

3

7

64

4

java代码编译_java eclipse 编译_java代码编译

8

128

4

10

我们通过标志CICompilerCount来查看当前jvm的线程数量,这是jvm处理编译队列的总线程数:

[root@hecs-402944 opt]# jinfo -flag CICompilerCount 11210
-XX:CICompilerCount=2
复制代码

我的服务器是2核,所以是2。其中包含一个client线程和server线程。

内联

方法内联是编译器当中做的最重要的性能优化。我们熟悉的java实体类,通常都会为每个属性添加getter和setter方法,这种方法的调用相比于直接访问变量,会有较大的性能开销。

java代码编译_java eclipse 编译_java代码编译

jvm当中方法调用,存在于虚拟机栈的栈帧当中,整个调用链较长,会有较大的性能损耗。

有如下的代码:

static class Student {
    private String name;
    private String firstName;
    
    private String secondName;
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    public String getSecondName() {
        return secondName;
    }
    public void setSecondName(String secondName) {
        this.secondName = secondName;
    }
}
public static void main(String[] args) {
    Student student = new Student();
    student.setName(student.getFirstName() + student.getSecondName());
}
复制代码

在jvm帮助我们在编译时进行内联后,就会有如下的代码:


public static void main(String[] args) {
    Student student = new Student();
    student.name = student.firstName + student.secondName;
}
复制代码

如上所示,已经将get和set方法的调用进行替换为直接属性的调用。

可以通过如下方式查看内联属性:

[root@hecs-402944 opt]# jinfo -flag Inline 11210
-XX:+Inline
复制代码

默认是开启的,此参数对性能影响巨大,不建议关闭。

java代码编译_java eclipse 编译_java代码编译

内联的条件

触发方法内联是有条件的,不是所有的代码都会被内联。

是否可以被内联取决于方法代码是否够热和它的大小。

逃逸分析

逃逸分析简单来说就是检查变量,查看变量的使用位置,检测其是否被其他范围所使用。如果它没有超出范围,那就是一个局部变量,我们能够针对这个变量做更多的优化。

如果被外部的方法调用,则称之为方法逃逸。 如果被外部的线程调用,则称之为线程逃逸。

在java8当中逃逸分析是默认被开启的:

[root@hecs-402944 opt]# jinfo -flag DoEscapeAnalysis 11210
-XX:+DoEscapeAnalysis
复制代码

开启逃逸分析后,server编译器将会进行很激进的优化:

当然还有很多复杂的优化,这里不过多介绍java代码编译,因为不建议我们针对逃逸分析做优化。

但是我们可以就逃逸分析解决一些问题:

原文链接: