JVM学习(一)

一、jvm基础

1. java从编译到执行

1)xxx.java文件通过javac命令执行成xxx.class文件

2)xxx.class文件通过java命令和classLoader加载到内存。另外,java类库也会加载到内存中。

3)调用字节码解释器或者JIT(即时编译器)进行解释或编译

4)编译完成后,由执行引擎进行执行

5)执行引擎下面是操作系统和硬件

2. jvm是跨平台的

jvm与java无关,jvm只是一种规范

任何语言,只要能编译成class文件,都可以在jvm上运行

同一个源文件,在windows和Linux上都能执行,不用修改任何东西(C和C++做不到)

jvm是一台虚拟的计算机

3. jvm常见的实现

关于java收费

其实是hotspot8之后的版本需要收费(17之后又开始不收费了),但是hotspot提供了一个免费的版本,Open JDK。也可以用TaobaoVM

4. jvm、jre、jdk

jdk>jre>jvm

二、class文件

1. class文件格式

 可以用sublime或者notepad查看16进制格式的class文件,还可以用idea的插件BinEd

javap xxx.class命令,可以查看反编译的内容

javap -v xxx.class命令,可以查看详细的class文件的格式内容

同idea的Show ByteCode

JBP可以修改二进制文件

JClassLib(idea插件)也可以查看class的 

 

结果: 

根据class的16进制字节码含义:

2. 类加载过程

1)Loading(把class文件加载到内存中)

2)Linking

        2.1)Verification(校验是否符合标准)

        2.2)Preparation(把class文件的静态变量赋默认值

        2.3)Resolution(把class文件中,常量池里面用到的符号引用转换成直接的内存地址)

3)Initializing(静态变量赋初始值

3. 类加载器

 Bootstrap类型的类加载器会返回null

4. 类加载过程(采用双亲委派机制)

 有一个class文件需要被加载到内存时,
1. 调用自定义CustomClassLoader的Custom.loadClass方法,如果在内存中找到了,返回结果;
2. 如果没找到,找到父加载器AppClassLoader,再在内存中找,如果找到了,返回结果;
3. 如果没找到,找到父加载器ExtClassLoader,再在内存中找,如果找到了,返回结果;
4. 如果没找到,找到父加载器Bootstrap,再在内存中找,如果找到了,返回结果;
5. 如果没找到,反过去让ExtClassLoader找到class并加载,如果加载成功,返回结果
6. 如果没有加载成功,让AppClassLoader找class并加载,如果加载成功,返回结果
7. 如果没有加载成功,让CustomClassLoader找class并加载,如果加载成功,返回结果
8. 如果没有加载成功,抛异常ClassNotFoundExecption

***这些定义来自于Launcher类

5. 为什么要用双亲委派加载类

主要为了安全,还有资源浪费问题

比如说String类如果使用自定义的类加载器会有很大的安全隐患,可以随意修改,所以需要使用定义好的Bootstrap类加载器来加载;还有就是,上面如果已经定义好了,再加载一遍造成资源浪费

6. 自定义类加载器

继承ClassLoader,重写findClass方法

7. java是解释执行的还是编译执行的

混合模式的,既可以用解释器也可以用编译器

 三、JMM

1. 存储器的层次结构 

 越往上,容量越小,速度越快

从硬盘上读取数据到cpu上执行:
1)在硬盘上有一个数a,首先被load到内存
2)cpu读的时候,尝试去高速缓存L1中找,如果在,直接给cpu;

3)如果没有,去L2中找;如果L2中有,load到L1中并交给cpu

以此类推
 

2. 数据一致性问题

因为L1和L2在cpu内部,当cpu1改变变量a的值为1,cpu2改变a的值为2,就会出现数据不一致的问题

解决方案:

1)总线锁,总线锁会锁住总线,使得其他cpu不能访问内存中其他地址,效率很低

2)一致性协议,MESI Cache 【并发编程】MESI--CPU缓存一致性协议 - 风动静泉 - 博客园

现代CPU的数据一致性实现 = 缓存锁(MESI)+ 总线锁

3. 缓存行(cache line)

读取内存中的某个数据时,会把它附近的一块数据都读取出来,那一块数据称为缓存行

 目前多数是64字节

4. 伪共享

位于同一缓存行的两个不同的数据,被两个不同的CPU锁定,产生互相影响的伪共享问题

对缓存行进行对齐,可以解决伪共享的问题,提高效率,但是对浪费一定的空间

四、有序性

1. 乱序

CPU为了提高指令执行效率,会在一条指令执行过程中(比如去内存读取数据),去同时执行另一条指令,前提是,两条指令没有依赖关系

现代cpu的合并写技术对程序的影响 - 刘少东的博客 - 博客园

写操作也可以合并

volatile可以保证有序

有序性保障(硬件级别)

1)CPU内存屏障

2)intel lock汇编指令

2.如果保证特殊情况下不乱序

1)硬件内存屏障

2)JVM级别

JVM级别的只是一种规范,还是依赖于硬件层面实现

3. volatile实现有序

1)字节码层面

有一个ACC_VOLATILE标记

2)JVM层面

volatile内存区的读写都加屏障

 3)OS和硬件层面

 volatile与lock前缀指令_zhifeng687的博客-CSDN博客

4. synchronized实现同步

synchronized不可以保证有序性

1)字节码层面

 在代码块前后加monitorenter和monitorexit指令

在方法上加ACC_SYNCHRONIZED标记

2)JVM层面

C、C++调用了操作系统提供的同步机制

3)OS和硬件层面

X86 : lock comxchg  xxxx

Java使用字节码和汇编语言同步分析volatile,synchronized的底层实现_21aspnet的博客-CSDN博客

5.happens-before原则

不管如何重排序,单线程执行结果不会改变

五、对象的内存布局

1. 对象的创建过程

2. 对象在内存中的存储布局

 3. 对象头markword具体包含什么

一个字节是8位,也就是8bit,4bit可以存储最大的2的4次方-1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值