本文是笔者 Java 学习笔记之一,旨在总结个人学习 Java 过程中的心得体会,现将该笔记发表,希望能够帮助在这方面有疑惑的同行解决一点疑惑,我的目的也就达到了。欢迎分享和转载,转载请注明出处,谢谢合作。由于笔者水平有限,文中难免有所错误,希望读者朋友不吝赐教,欢迎斧正。(可在文末评论区说明或索要联系方式进一步沟通。)
Java 创建对象的方式:
new
关键值调用构造方法创建对象实例;- 使用反射机制创建对象实例,(如:使用类的
Class
对象调用newInstance
方法创建对象实例,使用类加载器ClassLoader
的loadClass
方法获取类的Class
对象,调用newInstance
方法创建对象实例); - 使用
clone
方法从一个对象创建一个克隆对象实例; - 使用反序列化从一个对象的序列化版本创建一个对象实例;
- 加载过程中虚拟机会创建
Class
对象来存放该类的类信息; String
对象。
Java 垃圾回收算法:
- 引用计数算法(Java不使用),无法解决对象相互引用的问题;
- 可达性分析算法,通过一些列 GC Roots 的对象作为起点,往下搜索,不被任何一个引用链相连的为不可达,也就是无法被引用的对象,可作为 GC Roots 的一般有:
- 方法区中的常量、静态变量引用的对象;
- 虚拟机栈中的局部变量表;
- Native 方法栈中引用的对象;
- 对于不同的内存区域要使用不同的垃圾回收算法或者组合,对于不同内存区域常用的算法如下:
- 方法区(类信息,常量,静态变量),主要回收废弃常量和无用的类;
- 垃圾回收算法:
- 标记-清除法(Mark-Sweep),碎片化;
- 复制算法(Copying),浪费一半(或10%,一个 Eden,两个 Survivor 区);
- 标记-整理法(Mark-Compact),占用和空闲的分别移动到两端;
内存分配与回收策略:
- 对象优先在 Eden 区分配,不够时 Minor GC;
- 大对象直接进入老年代,容易导致空间不少但提前触发垃圾收集以获得足够的连续空间;
- 长期存活的对象进入老年代,age 计数器,
类加载过程:
类从被加载到虚拟机内存中开始,到被卸载出内存为止,整个生命周期包括:装载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)、卸载(Unloading)。
- 在类装载阶段,虚拟机要做以下几件事:
- 通过一个类的全限定名获取定义此类的二进制字节流;获取二进制字节流的方式可能有:
- 从本地文件系统装在一个 Java class 文件;
- 从网络下载一个 Java class 文件(如 Applet);
- 从压缩包(如 jar,ear,war,zip 等)提取 java class 文件;
- 从数据库中提取 class 文件;
- 从 java 源文件动态编译的 class 文件;
- 动态为某个类型计算 class 文件数据(如 cglib );
- 将该字节流所代表的静态存储结构转换为存放在方法区中的运行时数据结构;
- 生成代表该类的 java.lang.Class对象,作为方法区这个类的访问入口。
- 通过一个类的全限定名获取定义此类的二进制字节流;获取二进制字节流的方式可能有:
- 在准备阶段,虚拟机要为类变量分配内存,设置默认初始值(如 整型类型为 0 ,引用类型为 null),准备阶段不会执行 java 代码,所以像 int a = 10;在准备阶段 a 为 0,初始化阶段才为 10;
- 在解析阶段,虚拟机要在常量池中搜索类,接口字段,方法的符号引用,然后转换为直接引用;在符号引用被程序首次使用之前,解析是可选的;
- 在初始化阶段,虚拟机要为类变量赋予正确的初始值(也就是程序员想要赋予的初始值,如上面例子中的 int a = 10;此时 a 的正确初始值为 10);所有的类初始化操作和静态初始化代码被编译器收集到一个方法中,即
<clinit>
;只有需要使用 Java 代码来赋予类变量正确初始值的类才有<clinit>
方法,初始化一个类包含两个步骤:
- 如果存在直接超类,且超类还没被初始化,则初始化之;
- 如果类存在一个初始化方法,执行之;
只有在虚拟机首次主动使用类型时初始化它们,主动使用包含以下活动: - 创建类的实例
- 调用类的静态方法
- 操作类的非常量静态字段
- 调用该类相关的反射方法
- 初始化一个类的子类
- 指定为虚拟机启动的 main 方法的类
类加载器类别:
- 启动类加载器(Bootstrap ClassLoader):加载 lib/rt.jar;
- 扩展类加载器(Extension ClassLoader):加载 lib/ext.jar;
- 应用程序类加载器(Application ClassLoader):也叫系统类加载器,由 ClassLoader#getSystemClassLoader 返回,负责加载类路径(ClassPath)中的类库;