编译:“.java”文件打包,会编译成“.class”文件。
类加载器 :类加载器会把编译好的“.class”字节码文件加载到JVM中。
Q:怎么防止公司核心源码被窃取?
R:在编译过程中,对字节码进行加密,或者做混淆处理。在类加载的时候,对加密的类,考虑采用自定义的类加载器来解密文件即可。
类加载到使用的过程:加载→验证→准备→解析→初始化→使用→卸载
验证:校验“.class”文件完全符合JVM规范。
准备:给类分配一定的内存空间,类变量(static修饰的变量)分配内存空间 ,给一个默认的初始值"0"。
解析:符号引用替换成直接引用的过程。
核心阶段 初始化:执行类的初始化代码,比如完成配置项的读取,然后赋值给这个类变量
什么时候会初始化:1、“new ReplicaManager()”来实例化对象,会触发类的加载到初始化 的过程,把这个类准备好,然后再实例化一个对象出来。
2、或者是包含“main()“方法的类,必须立马初始化。
3、初始化一个类的时候,必须先初始化它的父类
类加载器:
1、启动类加载器(Bootstrap ClassLoader):java安装目录下的”lib“目录中的核心类库
2、扩展类加载器(Extension ClassLoader):java安装目录下的”lib\ext“目录中的类
3、应用程序类加载器(Application ClassLoader):加载”ClassPath“环境变量所指定路径中的类,就是加载自己写的代码
4、自定义类加载器:根据自己的需求加载自己的类
双亲委派机制:JVM的类加载是有亲子层级结构的,就是说启动类加载器是最上层的,扩展类加载器是在第二层,第三层是应用程序类加载器,最后是自定义类加载器
需要加载类的时候先委派父类加载器去加载,最终传到顶层的类加载器,如果父类没找到这个类,会下推加载权利给子类加载器
Q:Tomcat的类加载机制应该怎么设计,才能把我们动态部署进去的war包中的类,加载到Tomcat自身运行的JVM中,然后去执行那些我们写好的代码呢?
R:Tomcat自定义了common、catalina、shared等类加载器,其实就是加载Tomcat自己的一些核心基础类库的。每个Web应用都准备一个WebApp类加载器。每个Jsp也都准备一个Jsp类加载器。
Tomcat是打破双亲委派机制,WebApp负责加载对应的Web应用的".class"文件,不会传导给上层类加载器去加载。
JVM内存区域:
存放类的方法区:元数据空间(Metaspace)存放我们自己写的各种类相关的信息。
执行代码指令用的程序计数器:用来记录当前执行的字节码指令的位置。
java虚拟机栈:保存每个方法内的局部变量等数据,每个线程都有自己的java虚拟机栈。如果线程执行一个方法,就会对这个方法调用创建对应的一个栈帧。栈帧里就有这个方法的局部变量表,操作数栈,动态链接,方法出口。
Java虚拟机栈作用:调用执行任何方法的时,都会给方法创建栈帧然后入栈,在栈帧里存放了这个方法对应的局部变量之类的数据,包括这个方法执行的其他相关信息,方法执行完毕之后就出栈。
Java堆内存:存放我们在代码中创建的各种对象。
Q:Java堆内存中分配的哪些对象,到底会占用多少内存?一般怎么来计算和估算我们的系统创建的对象对内存占用的一个压力呢?
R:对象对内存空间的占用,大致分两大块,一个是对象自己本身的一些信息。一个是对象的实例变量作为数据占用的空间 。
JVM垃圾回收机制:如果某个实例对象没有任何一个方法的局部变量指向他,也没有任何一个类的静态变量,包括常量等地方在指向它。那么这个垃圾回收线程,就会把这个没人指向的“RepilcaManager”实例对象给回收掉,从内存里清除掉,让他不在占用任何内存资源 。
Q:加载到方法区的类会被垃圾回收吗?什么时候被回收?为什么呢?
R:该类的所有实例对象都已经从java堆内存里被回收,其次加载这个类的ClassLoader已经被回收,最后对该类的Class对象没有任何引用。
记录知识点:
java支持多线程,每个线程有自己的java虚拟机栈和本地方法栈。
新建的实例在堆内存,实例变量也在堆内存里。