流程:字节码文件(.class) -> 类加载 -> 类链接 -> 类初始化 -> 对象初始化 -> 对象创建 -> 对象使用 -> 对象回收 。

1、Java类的链接
(1)回顾:Java虚拟机刚启动时,内部只包含Java核心类的相关信息,随着程序的运行,不断有新的Java类被加载到虚拟机中,变为可用状态。Java类被加载后还需要经过链接和初始化才可以在虚拟机中使用。
(2)链接:把加载到Java类的字节代码中包含的信息虚拟机的内部信息进行合并,使Java类的代码可以被执行。链接分为3个子步骤,分别为验证、准备和解析。链接过程中,会对Java类的直接父类或父接口进行验证和准备,但是对类中形式引用的解析是可选的。
(3)验证:用来确保Java类的字节代码表示在结构上完全正确,且可能使得其他Java类或接口被加载。如果发现字节代码的格式不正确,会抛出java.lang.VerifyError错误。
(4)准备:创建Java类中的静态域,并将这些域的值设置为默认值,并不执行代码,为了确保类加载时的类型安全。由于可能出现两个不同的类加载器同时加载同一个Java类,导致无法记录下哪个才是该Java类的初始类加载器,所以会抛出java.lang.LinkageError错误。
(5)解析:处理所加载的Java类中包含的形式引用。如:父类、所实现接口、方法的形式参数和返回值的Java类等。这些形式引用对应的Java类都被正确加载之后,当前Java类才能正常工作。在Java类中可能包含了对其他类中方法的调用,对这些方法调用,在解析过程需要检查所调用的方法确实存在
(6)解析策略:由于有一些类具有复杂的引用关系图,所以需要使用不同的策略来解决:
  • 提前解析:在链接时递归地对依赖的所有形式引用都进行解析,性能差。
  • 延迟解析:在真正需要一个形式引用才进行解析。
2、Java类的初始化
(1)过程:静态域 -> 静态代码块(这个方面教程比较多,不贴代码了)
(2)可能造成类初始化的操作:
  • 创建一个Java类实例对象,如:Student s  = new Student();
  • 调用一个Java类的静态方法,如:StringUtils.substring();
  • 为类或接口中的静态非final域赋值(常量是在编译时进行初始化,放在常量池中,即运行时与该类并无直接关系了)
  • 调用Class类和反射API中进行反射操作的方法,如:Class.forName("xxx");
3、对象的初始化与创建
(1)过程:父类的代码块 -> 父类的构造器 -> 子类的代码块 -> 子类的构造器
(2)注意:不要在构造方法中调用可以被子类覆盖的方法。
class Animal {
public Animal() {
int average = 30 / getCount();
}
protected int getCount() {
return 4;
}
}
class Dog extends Animal {
private int count;
public Dog(int count) {
this.count = count;
}
public int getCount() {
return count;
} }
public class WrongInit {
public static void main(String[] args) {
Dog dog = new Dog(4); //抛出了除零异常
}
}
4、对象终止
(1)finalize方法:基本没用,由于调用时间无法确定,System.gc()虽然可以提升垃圾回收的几率,进而增加finalize方法被运行的几率,但实际运行时间还是无法确定。
(2)finalize方法与资源释放:不要在finalize中进行资源释放,回收时间不确定可能导致打开资源过多,导致系统崩溃,使用显式释放(inputStream.close()等)或者使用try-with-resources语句来进行资源释放
(3)正确使用finalize方法:
  • 必须调用父类的finalize方法进行内存回收
  • finalize方法中过多的语句,可能导致对象复活,可以使用幽灵引用来代替
5、对象复制
(1)被复制的类需要实现Cloneable接口,不然调用clone方法,将抛出CloneNotSupportedException异常
(2)浅克隆:基本类型和不可变对象的域,如果包含引用类型,会导致复制出来的对象与原对象的引用指向了同一个对象
class Counter {
private int value = 0; public void increase() {
value++;
} public int getValue() {
return value;
}
} class MutableObject implements Cloneable {
private Counter counter = new Counter(); public void increase() {
counter.increase();
} public int getValue() {
return counter.getValue();
} public Object clone() {
try {
return super.clone();
} catch (Exception e) {
throw new Error(e);
}
}
} public class MutableObjectClone {
public static void cloneObject() {
MutableObject obj = new MutableObject();
obj.increase();// 1
MutableObject cloneObj = (MutableObject) obj.clone();
cloneObj.increase();// 2
obj.increase();// 3
System.out.println(cloneObj.getValue());
} public static void main(String[] args) {
cloneObject(); // 3
}
}
(3)深克隆:引用类型也克隆一份,这需要递归克隆。
class Counter {
private int value = 0; public void increase() {
value++;
} public int getValue() {
return value;
} public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
throw new Error(e);
}
}
} class MutableObject implements Cloneable {
private Counter counter = new Counter(); public void increase() {
counter.increase();
} public int getValue() {
return counter.getValue();
} public Object clone() {
MutableObject obj = null;
try {
obj = (MultableObject)super.clone();
obj.counter = (Counter)counter.clone();
return obj;
} catch (Exception e) {
throw new Error(e);
}
}
} public class MutableObjectClone {
public static void cloneObject() {
MutableObject obj = new MutableObject();
obj.increase();// 1
MutableObject cloneObj = (MutableObject) obj.clone();
cloneObj.increase();// 2
obj.increase();// 2
System.out.println(cloneObj.getValue());
} public static void main(String[] args) {
cloneObject(); // 2
}
}
6、对象序列化(实现Serializable,不然抛出 java.io.NotSerializableException)
(1)序列化:活动对象的内部状态转换成一个字节流;
public class WriterUser{
public void write(User user) throws IOException{
Path path = Paths.get("user.bin");// 相当于项目目录下的user.bin文件
try(ObjectOutputStream output = new ObjectOutputStream(Files.newOutputStream(path))){
output.writeObject(user);
}
} public static void main(String[] args) throws IOException{
WriterUser writeUser = new WriterUser();
User user = new User("Alex","alex@example.org");
writerUser.write(user)
}
}
(2)反序列化:字节流转换成可以直接使用的Java对象。
public class ReadUser{
public User readUser() throws IOException,ClassNotFoundException{
Path path = Paths.get("user.bin");
try(ObjectInputStream input = new ObjectInputStream(Files.newInputStream(path))){
User user = (User)input.readObject();
return user;
}
} public static void main(String[] args) throws ClassNotFoundException,IOException{
ReadUser readUser = new ReadUser();
User user = readUser.readUser();
System.out.println(user.getName());//Alex
}
}
(3)自定义序列化:因为序列化之后的对象可能包含敏感信息,需要去除。
//在User类中添加如下方法
private void writeObject(java.io.ObjectOutputStream out) throws IOException {
System.out.println("write object start");
//out.defaultWriteObject(); //默认形式,注掉可让邮件信息不序列化
out.writeUTF(getName());
} private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
System.out.println("read object start");
//in.defaultReadObject();
this.name = in.readUTF(); //由于没有存入邮件信息,所以获取邮件信息时将得到null值
}
//多个String的域,按顺序存入,按顺序取出即可
//有了这两个方法,可以对存入信息进行加密,取出来时进行解密

  

 
 

java7:核心技术与最佳实践读书笔记——对象生命周期的更多相关文章

  1. java7:核心技术与最佳实践读书笔记——类加载

    流程:class -> 加载 ->  jvm虚拟机 -> 链接 . 一.类加载器概述 1.引出      类加载器也是一个java类,java.lang.ClassLoader类是所 ...

  2. java7:核心技术与最佳实践读书笔记——字节代码格式

    一般流程:开发人员写出java源代码(.java) ->  javac(编译器) -> java字节代码(.class) -> 加载 -> java虚拟机(jvm)运行. 1. ...

  3. 《深入理解Java7核心技术与最佳实践》读书笔记(1.1)---Project Coin介绍

    OpenJDK中的Coin项目(Project Coin)的目的就是为了收集对Java语言的语法进行增强的建议.在Coin项目开始之初,曾经广泛地向社区征求提议.在短短的一个月时间内就收到将近70条提 ...

  4. php核心技术与最佳实践(笔记一)

    1.1面向对象的型与本 类是对象的抽象组织,对象是类的具体存在. 1.1.1对象的形 <?php class Person{ public $name; public $gender; publ ...

  5. PHP核心技术与最佳实践——全局浏览

    难得买到并喜欢一本好书,‘PHP核心技术与最佳实践’. 几天时间,先看了个大概,总结一下整体是什么样子的,怎么看怎么学. 1.总共14章: 2.第1.2章讲PHP的OOP: 其中第一章侧重于PHP的O ...

  6. Thinking In Java读书笔记--对象导论

    Thinking In Java读书笔记--对象导论[对象]服务提供者==>将对象看做一个服务提供者[程序员分类][类创造者]/[客户端程序员] [访问控制存在的原因?][1]客户端程序员无法触 ...

  7. 《深入理解OSGi:Equinox原理、应用与最佳实践》笔记_1_运行最简单的bundlehelloworld

    <深入理解OSGi:Equinox原理.应用与最佳实践>笔记_1_运行最简单的bundlehelloworld 买了周大大的OSGI的书看 先前完全没有基础 就靠这本书看看学学 顺便记一些 ...

  8. 温习《PHP 核心技术与最佳实践》这本书

    再次看这本书,顺手提炼了一下大致目录,以便后续看见目录就知道大概讲的些什么内容 PHP 核心技术与最佳实践 1.面向对象思想的核心概念 1.1 面向对象的『形』与『本』 1.2 魔术方法的应用 1.2 ...

  9. ASP.NET Core Web API下事件驱动型架构的实现(二):事件处理器中对象生命周期的管理

    在上文中,我介绍了事件驱动型架构的一种简单的实现,并演示了一个完整的事件派发.订阅和处理的流程.这种实现太简单了,百十行代码就展示了一个基本工作原理.然而,要将这样的解决方案运用到实际生产环境,还有很 ...

随机推荐

  1. RISC-V riscv64-unknown-elf

    riscv64-unknown-elf 为 RISC-V指令集的交叉编译工具 以下环境在Liunx ubuntu x86_64 环境下进行,下面示例以生成32位文件为目标来操作使用. screen / ...

  2. <JavaScript>谈谈javascript语法里一些难点问题(一)

    1)    引子 前不久我建立的技术群里一位MM问了一个这样的问题,她贴出的代码如下所示: var a = 1; function hehe() { window.alert(a); var a = ...

  3. SQL-W3School-高级:SQL LEFT JOIN 关键字

    ylbtech-SQL-W3School-高级:SQL LEFT JOIN 关键字 1.返回顶部 1. SQL LEFT JOIN 关键字 LEFT JOIN 关键字会从左表 (table_name1 ...

  4. js for (i=0;i<a.length;a[i++]=0) 中等于0怎么理解?

    js的问题for (i=0;i<a.length;a[i++]=0) 中等于0怎么理解? 很奇怪的一个for循环 竟然是将原来数组的数据全改为0

  5. 浅谈smarty模板的mvc框架

    最近接触了一个大项目,php做的后台管理,融合了smarty模板+mvc框架+phpcms内容管理,,,这个项目简直就是php的精华,于是小编大哥对项目小女子产生了兴趣,打算一点一点把她征服.现在小吃 ...

  6. kafka-sparkstreaming---学习1

    ---恢复内容开始--- import java.util.*; import org.apache.spark.SparkConf; import org.apache.spark.TaskCont ...

  7. js的event详解

    event代表事件的状态,例如触发event对象的元素.鼠标的位置及状态.按下的键等等.event对象只在事件发生的过程中才有效.event的某些属性只对特定的事件有意义.比如,fromElement ...

  8. Spring Security(01)——初体验

    (注:本文是基于Spring Security3.1.6所写) (注:原创文章,转载请注明出处.原文地址:http://elim.iteye.com/blog/2154299) (注:本文是基于Spr ...

  9. 生动详细解释javascript的冒泡和捕获

    原文:Event order 翻译:hh54188的博客 前言:虽然精通jquery,但对它的原型javascript却不是很了解,最近在学习javascript中遇到了一些困难,比如冒泡和捕获,很多 ...

  10. Linux 基本权限管理

    1.linux权限表示: -rw-r--r-- (一共10位): 第一位:表示文件类型: 常用的三种文件类型:- 表示一般文件,d 表示目录,l 表示软链接文件: 后九位:每三位为一组: rwx r- ...