jdk8源码阅读-1.1-java.lang.Object

Object类是类层次结构的根,每个类都有Object类作为父类。所有对象,包括数组,都实现了这个类的方法。

一.private static native void registerNatives();

csharp 复制代码
private static native void registerNatives();
static {
        registerNatives();
    }

native修饰符表明该方法实现并不是Java语言编写,而是由C/C++编写。registerNatives()方法的主要作用是将C/C++中的方法映射到Java中的native方法,实现方法命名的解耦。

同时该方法的唯一使用就是在下方的同步代码块,static代码块执行时机是在类加载过程的初始化阶段,初始化阶段就是执行类构造器()方法的过程,()方法是由编译器自动收集类中的所有类变量的赋值动作和静态语句块(static{})中的语句合并而成,Java虚拟机会保证在子类的()方法执行前,父类的()方法执行完毕。因此在Java虚拟机中第一个被执行的()方法的类型肯定是java.lang.object。(《深入理解Java虚拟机》)

二.public final native Class<?> getClass();

返回此对象的运行时类对象。返回的Class对象是由所表示类的静态同步方法锁定的对象。同时该方法也是一个本地方法。

三.public native int hashCode();

返回对象的Hash码。

hashCode的约定为:

  1. 程序运行期间多次调用该方法返回的整数值应该相同,前提是对象上用于相等比较的属性没有被更改。在程序的两次不同执行时不必保持一致
  2. 使用equals(Object)方法若判断两个对象为真,则两个对象的hash码返回值必须相同
  3. 不同的对象的hash码不要求必须不同(Java可以实现强制不同,但是没有必要)

四.public boolean equals(Object obj) ;

指示其他对象是否"等于"此对象。

有以下性质:

  1. 自反性:对于任意非空的对象,和自身比较永远相等
  2. 对称性:如果A.equals(B)为真,B.equals(A)也为真
  3. 可传递性:A.equals(B)和B.equals(C)为真,A.equals(C)也为真
  4. 一致性:多次调用该方法返回的值保持相同

注意,每当重写hashCode方法时,通常都需要重写该方法,以便维护hashCode方法的一般约定,该约定规定相等的对象必须具有相等的哈希码。

五.protected native Object clone() throws CloneNotSupportedException;

创建并返回此对象的副本。

官方注释:

类Object的方法clone执行特定的克隆操作。首先,如果该对象的类没有实现接口Cloneable,则会抛出CloneNotSupportedException异常。注意,所有数组都被认为实现了接口Cloneable,数组类型T[]的克隆方法的返回类型是T[],其中T是任何引用类型或基本类型。否则,此方法将创建此对象的类的新实例,并使用该对象对应字段的内容初始化其所有字段,就像通过赋值一样;字段的内容本身并不是克隆的。因此,该方法执行该对象的"浅拷贝",而不是"深拷贝"操作。

此外在Object类上进行clone也会抛出异常,因为没有实现Cloneable接口

六.public String toString();

返回对象的字符串表示形式。

具体实现为:return getClass().getName() + "@" + Integer.toHexString(hashCode());

该字符串由该对象作为其实例的类的名称、@符号字符' @'以及该对象哈希码的无符号十六进制表示形式组成。由于最后一个组成部分是对象的哈希码,因此同一个类的两个不同对象调用该方法仍有可能相等

七.public final native void notify();

唤醒正在此对象的监视器上等待的单个线程。如果有线程正在等待此对象,则选择其中一个线程来唤醒。这种选择是任意的,是在执行过程中自行决定的。

运用JUC并发编程解释相关概念:

每个Java对象都可以关联一个Monitor对象,如果使用synchronized给对象上锁(重量级)之后,该对象头的Mark Word中就设置指向Monitor对象的指针

编辑

  • 刚开始Monitor中Owner为null
  • 当Thread-2执行synchronized(obj)就会将Monitor中的Owner置为Thread-2,Monitor中只能有一个Owner
  • 在Thread-2上锁的过程中,如果Thread-3,Thread-4,Thread-5也来执行synchronized(obj),就会进入EntryList Blocked
  • Thread-2执行完同步代码块的内容,然后唤醒EntryList中等待的线程来竞争锁,竞争的时候是非公平的
  • WaitSet中的Thread-0,Thread-1是之前获得过锁,但条件不满足进入WAITING状态的线程

其中,obj.notify()在object上正在WaitSet等待的线程中挑一个唤醒,但唤醒后并不意味立刻获得锁,仍需进入EntryList重新竞争

八.public final native void notifyAll();

唤醒在该对象的监视器上等待的所有线程。

九.public final native void wait(long timeout) throws InterruptedException;

导致当前线程等待,直到另一个线程调用此对象的object .notify()方法或object . notifyall()方法,或者经过指定的时间。并且同时会释放对象锁。

线程T为线程调度目的而被禁用,并处于休眠状态,直到发生以下四种情况之一:

  1. 其他线程调用这个对象的notify方法,而线程T恰好被任意选择为要被唤醒的线程。
  2. 其他线程调用此对象的notifyAll方法。
  3. 其他线程中断线程T。
  4. 指定的实时时间或多或少已经过去了。但是,如果timeout为零,则不考虑实时,线程只是等待,直到收到通知。

十.public final void wait(long timeout, int nanos) throws InterruptedException;

与一个参数的wait方法相同,同样会导致当前线程等待。

看似在等待时长上实现了更精细的控制,实际阅读源码会发现其实与一个参数的差别不大,逻辑很简单,首先进行timeout和nanos的参数校验,若非法则抛出异常,之后将timeout++调用wait(timeout)方法,nanos实际只是将timeout数值加一,并没有实现更高精度。

十一.public final void wait() throws InterruptedException;

源码逻辑是调用wait(0)方法

十二.protected void finalize() throws Throwable { };

当垃圾回收确定不再有对对象的引用时,由垃圾回收器对对象调用。子类覆盖finalize方法以处置系统资源或执行其他清理。

在JVM的垃圾回收中要真正宣告对象的死亡,需要经历两次标记,第一次标记是由GC roots引用链到该对象不可达时会被第一次标记,随后进行一次筛选,筛选的条件是此对象是否有必要执行finalize()方法。如果该方法还未被执行,那么该对象就会被放在一个名为F-Queue的队列中,并在稍后由一条虚拟机自动建立的,低调度优先级的Finalizer线程去执行该方法。

它的运行代价高昂,并且不确定性大,无法保证各个对象的调用顺序,如今已被官方明确声明为不推荐使用的语法。(《深入理解Java虚拟机》)。

相关推荐
听风者就是我29 分钟前
混合检索:关键词 + 向量的最佳组合
后端·ai编程
Memory_荒年44 分钟前
当餐厅后厨也懂分布式:SpringBoot中的重试、限流、熔断与幂等的“四重奏”
java·后端·spring
刘晓飞1 小时前
nestjs 中的 rxjs
后端
编码忘我2 小时前
java策略模式实战之优惠券
java·后端
anzhxu2 小时前
SpringBoot 3.x 整合swagger
java·spring boot·后端
青椒啊2 小时前
DPDK入门到精通(一)
后端
小江的记录本2 小时前
【Bean】JavaBean(原生规范)/ Spring Bean 【重点】/ 企业级Bean(EJB/Jakarta Bean)
java·数据库·spring boot·后端·spring·spring cloud·mybatis
中国胖子风清扬2 小时前
Camunda 8 概念详解:梳理新一代工作流引擎的核心概念与组件
java·spring boot·后端·spring cloud·ai·云原生·spring webflux
前端付豪2 小时前
实现必要的流式输出(Streaming)
前端·后端·agent
go4it2 小时前
Java26的新特性
后端