• jiaobuchongจุ๊บ 置顶
    2018-10-14
    对老师写的那段 awk 不懂得可参考:
    https://blog.csdn.net/jiaobuchong/article/details/83037467
    
     58
  • 小名叫大明 置顶
    2018-07-26
    受益匪浅,多谢老师。

    请教老师一个问题,网上我没有搜到。

    服务器线程数爆满,使用jstack打印线程堆栈信息,想知道是哪类线程数太多,但是堆栈里全是一样的信息且没有任何关键信息,是哪个方法创建的,以及哪个线程池的都看不到。

    如何更改打印线程堆栈信息的代码(动态)让其打印线程池信息呢?
    展开
    
     29
  • 东方
    2018-07-20
    jvm把boolean当做int来处理

    flag = iconst_1 = true

    awk把stackframe中的flag改为iconst_2

    if(flag)比较时ifeq指令做是否为零判断,常数2仍为true,打印输出

    if(true == flag)比较时if_cmpne做整数比较,iconst_1是否等于flag,比较失败,不再打印输出


    展开

    作者回复: 字节码高手!

     1
     332
  • かっこいすぎる郑一凡
    2018-07-20
    我想问下,JVM是怎么区别出热点代码和非热点代码的?
     3
     80
  • 醉人
    2018-07-20
    解释执行 执行时才翻译成机器指令,无需保存不占内存。但即时编译类似预编译,编译之后的指令需要保存在内存中,这种方式吃内存,按照二八原则这种混合模式最恰当的,热点代码编译之后放入内存避免重复编译,而其他运行次数较少代码则解释执行,避免占用过多内存
    
     77
  • novembersky
    2018-07-20
    文中提到虚拟机会把部分热点代码编译成机器码,我有个疑问,为什么不把java代码全部编译成机器码?很多服务端应用发布频率不会太频繁,但是对运行时的性能和吞吐量要求较高。如果发布或启动时多花点时间编译,能够带来运行时的持久性能收益,不是很合适么?

    作者回复: 问得好!事实上JVM确实有考虑做AOT (ahead of time compilation) 这种事情。AOT能够在线下将Java字节码编译成机器码,主要是用来解决启动性能不好的问题。

    对于这种发布频率不频繁(也就是长时间运行吧?)的程序,其实选择线下编译和即时编译都一样,因为至多一两个小时后该即时编译的都已经编译完成了。另外,即时编译器因为有程序的运行时信息,优化效果更好,也就是说峰值性能更好。

    
     76
  • MARK
    2018-07-25
    作业终于做出来~\(≧▽≦)/~喜大普奔
    asmtools下载地址:
    https://adopt-openjdk.ci.cloudbees.com/view/OpenJDK/job/asmtools/lastSuccessfulBuild/artifact/asmtools-6.0.tar.gz;
    先是在window环境里,awk不能使用,看https://zh.wikipedia.org/wiki/Awk,AWK是一种优良的文本处理工具,Linux及Unix环境中现有的功能最强大的数据处理引擎之一,于是转战Linux,
    [root@localhost cqq]# javac Foo.java
    [root@localhost cqq]# java Foo
    Hello,Java
    Hello,JVM
    [root@localhost cqq]# java -cp /cqq/asmtools.jar org.openjdk.asmtools.jdis.Main Foo.class>Foo.jasm.1
    [root@localhost cqq]# ls
    asmtools.jar Foo.class Foo.jasm.1 Foo.java
    [root@localhost cqq]# vi Foo.jasm.1
    [root@localhost cqq]# awk 'NR==1,/iconst_1/{sub(/iconst_1/,"iconst_2")} 1' Foo.jasm.1>Foo.jasm
    [root@localhost cqq]# java -cp /cqq/asmtools.jar org.openjdk.asmtools.jasm.Main Foo.jasm
    [root@localhost cqq]# java Foo
    Hello,Java
    结果为啥是这个看点赞第一的高手;
    另外asmtools使用方式还可以这样子:
    java -jar asmtools.jar jdis Foo.class>Foo.jasm.1
    java -jar asmtools.jar jasm Foo.jasm
    展开
     1
     70
  • 掌心童话
    2018-07-21
    我只想问,你就没有教授的担忧?万一我拿今天的知识点去问面试者,答不上来咋办?
    
     38
  • godtrue
    2018-07-24
    1:为什么使用JVM?
    1-1:可以轻松实现Java代码的跨平台执行
    1-2:JVM提供了一个托管平台,提供内存管理、垃圾回收、编译时动态校验等功能
    1-3:使用JVM能够让我们的编程工作更轻松、高效节省公司成本,提示社会化的整体快发效率,我们只关注和业务相关的程序逻辑的编写,其他业务无关但对于编程同样重要的事情交给JVM来处理

    2:听完此节的课程的疑惑(之前就没太明白,原期待听完后不再疑惑的)
    2-1:Java源代码怎么就经过编译变成了Java字节码?
    2-2:JVM怎么就把Java字节码加载进JVM内了?先加载那个类的字节码?它怎么定位的?拿到后怎么解析的?不会整个文件放到一个地方吧?使用的时候又是怎么找到的呢?这些感觉还是黑盒
    2-3:JVM将内存区域分成堆和栈,然后又将栈分成pc寄存器、本地方法栈、Java方法栈,有些内存空间是线程可共享的,有些是线程私有的。现在也了解不同的内存区块有不同的用处,不过他们是怎么被划分的哪?为什么是他们,不能再多几种或少几种了吗?共享的内存区和私有的又是怎么控制的哪?
    展开

    作者回复: 总结得非常细致!
    2-1 其实是这样的,JVM接收字节码,要运行在JVM上只能选择转化为字节码。要是不想在JVM上跑,可以选择直接转化为机器码。

    2-2 类加载会在第三篇详细介绍。

    2-3 具体的划分都是实现细节。你也可以选择全部冗杂在一起。但是这样子做性能较高,因为线程私有的可以不用同步。

    
     32
  • Ryan-Hou
    2018-07-20
    在为什么Java要在虚拟机里执行这一节您提到,java语法复杂,抽象度高,直接通过硬件来执行不现实,但是同样作为高级语言为什么C++就可以呢?这个理由作为引入虚拟机这个中间层的原因不是很充分吧

    作者回复: 多谢指出!这里的直接运行指的是不经过任何转换(编译),直接在硬件上跑。即便是C++,也不可以直接运行。

    C++的策略是直接编译成目标架构的机器码,Java的策略是编译成一个虚拟架构的机器码。这个虚拟架构可以有物理实现(可以搜Java processor),也可以是软件实现,也就是我们经常接触到的JRE。

    
     29
  • 周仕林
    2018-07-23
    看到有人说热点代码的区别,在git里面涉及到的热点代码有两种算法,基于采样的热点探测和基于计数器的热点探测。一般采用的都是基于计数器的热点探测,两者的优缺点百度一下就知道了。基于计数器的热点探测又有两个计数器,方法调用计数器,回边计数器,他们在C1和C2又有不同的阈值。😂😂

    作者回复: 谢谢!

     1
     27
  • J
    2018-12-25
    在Windows使用不了awk工具(貌似有代替方案),所以结合其他小伙伴的答案和自己的思考,答案整理如下:
    小作业的过程是:
    1、写Java代码,生成java文件
    2、将java文件编译成class文件(字节码)
    3、执行字节码,输出两个Hello,world!
    4、使用asmtool工具将class文件生成jasm文件
    5、使用awt工具将jasm文件stackframe的flag改为iconst_2
    6、再次使用asmtool工具将jasm文件恢复成class文件
    7、执行字节码,输出一个Hello, world!
    由于Java虚拟机将boolean类型看成0或者1,在步骤5中将源代码中的flag修改成2,于是在步骤7中的运行过程中,if(2),true,执行输出;if(2 == 1),结果为false,不执行输出。
    展开
    
     18
  • 尔东
    2018-12-30
    1.Java代码首先编译为class文件,然后通过java虚拟机加载到方法区。Java虚拟机是一个独立的进程,执行方法区的代码。
    2.Java虚拟机把内存分为堆栈两种形式来存储运行时数据,包括线程共有的方法区和堆,以及线程私有的pc计数器,方法栈,naive方法栈
    3.Java虚拟机将字节码翻译成机器码执行的方法有两种,一种是解释执行,即逐条将字节码翻译成机器码并执行;第二种是即时编译,即将一个方法包含的所有字节码编译成机器码后再执行
    4.解释执行的好处是无需等待编译,即时编译的好处是速度更快。这里编译的概念并不是代码编译为字节码,而是字节码编译为机器码,字节码编译为机器码是由java虚拟机在运行程序的时候才会去做的,所以是运行时的开销。热点代码会通过即时编译来执行。
    5.HotSpot内置了多个即时编译器,包括C1、C2和Graal。
    6.Asmtools.jar下载地址https://ci.adoptopenjdk.net/view/Dependencies/job/asmtools/lastSuccessfulBuild/
    7.JVM将Boolean类型看作是int类型,true就是1,false就是0,flag如果改成2第二个判1等式就不成立,所以只有第一个判0等式通过。
    展开
     1
     16
  • ace
    2018-08-05
    最后awk那段分析了下。希望分析正确 也对大家有帮助
    1、NR==1,/iconst_1/ 是用于匹配行 匹配第一行到第一个出现iconst_1的行
    2、{}进行脚本执行。针对第一步中匹配的行执行内置的字符串函数sub 做替换
    3、1 都会被执行。在awk 1被计算为true,表现为默认操作 print $0 也就是打印整行
    整体效果是打印所以文本行,但第一个出现iconst_1的做替换。
    
     14
  • 陈树义
    2018-07-21
    asmtools.jar 是在哪里下载的,怎么在给的链接页面没找到。
    
     13
  • 志文
    2018-07-22
    Java 作为一门高级程序语言,它的语法非常复杂,抽象程度非常高,所以不能直接在硬件上执行。所以要引入JAVA虚拟机。
    我觉得理由不充分,JAVA为什么不能像c++一样直接转成机器码呢?从理论上是可以用编译器来实现这个的功能的。问题在于直接像c++那样编译成机器码,就实现不了跨平台了。那么是不是跨平台才是引入JAVA虚拟机的重要原因呢 。请老师解答
     1
     11
  • 踏雪无痕
    2018-07-20
    您好,我现在所在的项目经常堆外内存占用非常多,超过总内存的70%,请问一下有没有什么方法能观察一下堆外内存有什么内容?

    作者回复: 堆外内存的话,就把JVM当成普通进程来查找内存泄漏。可以看下Google Performance Tools相关资料

    
     10
  • 欲风
    2018-07-20
    方法区和元空间是一个概念吧,能不能统一说法到jdk8之后的版本~
     1
     9
  • kernel
    2018-08-13
    评论比文章精彩,学习到更多
    
     8
  • 临风
    2018-07-20
    我跟楼上的novembersky同学一样疑惑,对于性能要求高的web应用,为什么不直接使用即时编译器在启动时全部编译成机器码呢?虽然启动耗时,但是也是可以接受的

    作者回复: 通常,对于长时间运行的程序来说,大部分即时编译就发生在前几个小时。

    再之后的即时编译主要是一些非热点代码,以及即时编译器中的bug造成的反复去优化重新编译。

    
     8
我们在线,来聊聊吧