java是跨平台的语言。一次编译多端使用。究竟是如何实现的呢
1.首先编译器会将java 文件编译成class文件。然后在不同的平台使用对应的虚拟机。不同虚拟机的内装载系统将class文件转换平台能执行的机器码
jvm整体结构
类加载器
类装载器的几个步骤 加载 链接 初始化
加载:
1.取得类的二进制流
2. 内容转为方法区的数据结构
3. java堆中生成队形的java.lang.class对象
链接 分为3个步骤(验证 准备 解析)
验证:
--是否以0xCAFEBABE开头
--版本号是否合理(比如jdk6生成的class文件 运行在jdk7生成的class文件)
--引用的类是否存在
准备:
在方法区分配内存。静态变量的设置为默认值 并没有初始化 比如static i=1 准备阶段分配内存 i为0
初始化:
static{}语句执行
static变量初始化
方法区
主要存放类的描述信息 比如变量 方法等
java堆
运行时间创建的实例对象的存储空间(堆空间又分配 新生代 老年代 ) 堆是所有线程共享的一块儿空间
java栈
非共享空间 每个线程都有一块儿独立的栈 栈的大小决定了方法调用的深度
栈的运行机制是每次运行会将主内存的内容拷贝一块儿到自己的工作内存
这里会涉及到一个内容同步问题
工作内存执行store 主内存执行 write 则将工作内存的值 同步到主内存
主内存执行read操作 工作内存执行load操作 则将主内存同步到工作内存
可以主要到无论是主内存 或者是工作内存 数据同步都要做完上面2步数据才完全一致。但是当工作内存改变了一个变量的值 没有及时同步到主内存 或者调换过来主内存 更改了一个变量的值不能及时通知到工作内存会引起数据不一致问题
java提供volatile 关键字 可以让工作内存每次改变volatile修饰的变量 工作内存读写都直接操作主内存
本地方法栈
跟栈作用一样 只是给执行的本地方法分配栈空间(指的是实现了jni接口的非java语言编写的代码 比如c c++)
垃圾收集器
与c++不同 c++内存释放是需要程序员自己手动释放。容易产生内存泄漏 。java引入垃圾回收机制 采用复制 标记清楚 标记压缩等算法实现定期的对垃圾的释放
指令计数器
CPU是在多个线程不同的切换执行。计数器是保存每个线程当前执行的命令行位置