JVM内存分为四大块。程序计数器,堆内存,栈内存,方法区。
程序计数器就是程序计数器,用来记录虚拟机栈中栈帧中的指令执行位置。线程私有的,生命周期与线程相同。当前线程所执行的字节码行号指示器。唯一一块没有OutOfMemoryError的区域。
堆内存是指,存放Java实例对象的地方。GC在这里进行回收。
栈内存是指,一个线程一个的jvm栈,每个线程创建的时候都会创建一个jvm栈。jvm栈中存放的是栈帧,一个栈帧,就是一个方法,栈帧存放的是局部变量。
方法区放的是:类的信息,类的静态变量,类的常量,还有即使编译器编译后的代码(机器指令)。是线程共享的区域。
public static void main(String [] args){
String s = new String("1213");
}
方法的局部变量放在栈上,如果局部变量是基础类型,存放的是值。如果是非基础类型,放的是指向堆上对象的引用地址。
jvm虚拟机包含两个子系统和两个组件,
两个子系统是:Classloader子系统和Executionengine(执行引擎)子系统;两个组件分别是:Runtimedataarea(运行时数据区域)组件和Nativeinterface(本地库接口)组件。
运行时数据区域包含5部分:方法区,堆,虚拟机栈,本地方法栈,程序计数器
17,什么是本地库接口和本地方法库:(1)本地方法库接口:即操作系统所使用的编程语言的方法集,是归属于操作系统的。s
编译器(在windows下,javac.exe)将源代码(java文件)编译为字节码(bytecode),存放在class文件中。
字节码不能直接在机器上执行,而是通过虚拟机(windows下是java.exe)执行。具体的执行方式有两种:
1. 一般情况下解释执行。解释执行并不是“解释为用c++语言写成的程序”,而是jvm把字节码看成脚本,根据字节码中的指令,由JVM去调用实际的本地方法。
2. 在打开了JIT参数的前提下,jvm会把执行过程中发现的热点位置,由jvm内部的即时编译器编译为本地机器码直接执行。
编译器将java文件编译为class文件,解释器将class文件变为机器语言
部八种基本类型的变量,非基本类型的变量存放的是指向堆上的地址。
jvm的class加载机制:双亲委派机制。双亲委派机制要求,除了顶层的类加载器意外,任何类加载器都应该有自己的父加载器。
这种父子关系不是用继承实现的,而是用组合实现的。
一个类加载器收到加载请求,不会马上自己去加载这个类,而是会把这个请求发送给它的父加载器,每个加载器都是如此。所有加载类的请求会从底向上问询一遍父加载器。只有当父加载器不能加载这个类时,(搜索范围内找不到这个class文件),当前的类加载器才会自己尝试加载。
在其它语言中,一个库不仅包含类,还可能包括方法和数据;但是 Java 中的所有的
代码都必须写在类里
一个类是在首次被使用的时候被加载,而不是在main方法开始前全部一次性加载。
类加载大致流程:
1.通过类的全限定名获取其定义的二进制字节流
2.将这个二进制的静态数据结构转化为方法区的运行时结构
3.在java堆中,生成一个代表此类的java.lang.class对象,作为方法区中这些数据的访问入口。
双亲委派机制的好处是,一个class只能被一个类加载器加载,或者不能被加载。