主要内容:
2. 什么是类加载器?
ClassLoader oader = ClassName.class.getClassLoader();
ClassLoader ParentLoader = loader.getParent();
类加载器是一个用来加载类文件的类。Java源代码通过javac编译器编译成类文件。然后JVM来执行类文件中
的字节码来执行程序。类加载器负责加载文件系统、网络或其他来源的类文件。
3. 类加载器有哪些?
有三种默认使用的类加载器:Bootstrap类加载器、Extension类加载器和Application类加载器。每种类加载
器都有设定好从哪里加载类。
Bootstrap类加载器负责加载rt.jar中的JDK类文件,它是所有类加载器的父加载器。Bootstrap类加载器没有
任何父类加载器,如果你调用String.class.getClassLoader(),会返回null,任何基于此的代码会抛出
NullPointerException异常。Bootstrap加载器被称为初始类加载器。
而Extension将加载类的请求先委托给它的父加载器,也就是Bootstrap,如果没有成功加载的话,再从
jre/lib/ext目录下或者java.ext.dirs系统属性定义的目录下加载类。Extension加载器由
sun.misc.Launcherͅ ExtClassLoader实现。
第三种默认的加载器就是Application类加载器了。它负责从classpath环境变量中加载某些应用相关的类,
classpath环境变量通常由-classpath或-cp命令行选项来定义,或者是JAR中的Manifest的classpath属性。
Application类加载器是Extension类加载器的子加载器。通过sun.misc.Launcherͅ AppClassLoader实现。
4. 什么是双亲委派模型(Parent-Delegation
Model)?
JVM中加载类机制采用的是双亲委派模型,顾名思义,在该模型中,子类加载器收到的加载请求,不会先去
处理,而是先把请求委派给父类加载器处理,当父类加载器处理不了时再返回给子类加载器加载;
5. 为什么使用双亲委派模型?
因为安全。使用双亲委派模型来组织类加载器间的关系,能够使类的加载也具有层次关系,这样能够保证核
心基础的Java类会被根加载器加载,而不会去加载用户自定义的和基础类库相同名字的类,从而保证系统的
有序、安全。
6. Java内存分配基本概念
每运行一个java程序会产生一个java进程,每个java进程可能包含一个或者多个线程,每一个Java进程对应唯
一一个JVM实例,每一个JVM实例唯一对应一个堆,每一个线程有一个自己私有的栈。进程所创建的所有类的
实例(也就是对象)或数组(指的是数组的本身,不是引用)都放在堆中,并由该进程所有的线程共享。Java
中分配堆内存是自动初始化的,即为一个对象分配内存的时候,会初始化这个对象中变量。虽然Java中所有
对象的存储空间都是在堆中分配的,但是这个对象的引用却是在栈中分配,也就是说在建立一个对象时在堆和
栈中都分配内存,在堆中分配的内存实际存放这个被创建的对象的本身,而在栈中分配的内存只是存放指向
这个堆对象的引用而已。局部变量 new 出来时,在栈空间和堆空间中分配空间,当局部变量生命周期结束
后,栈空间立刻被回收,堆空间区域等待GC回收。
具体的概念:JVM的内存可分为3个区:堆(heap)、栈(stack)和方法区(method,也叫静态区):
堆区:存储的全部是对象,每个对象都包含一个与之对应的class的信息(class的目的是得到操作指令) ;jvm
只有一个堆区(heap),且被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身和数组本身;
栈区:每个线程包含一个栈区,栈中只保存基础数据类型本身和自定义对象的引用;每个栈中的数据(原始类
型和对象引用)都是私有的,其他栈不能访问;栈分为3个部分:基本类型变量区、执行环境上下文、操作指
令区(存放操作指令);
方法区(静态区):
被所有的线程共享,方法区包含所有的class(class是指类的原始代码,要创建一个类的对象,首先要把该类
的代码加载到方法区中,并且初始化)和static变量。方法区中包含的都是在整个程序中永远唯一的元素,如
class,static变量。