JAVA基础笔记1(JAVA运行原理及流程,JAVA内存与JVM,以及==,equals,hashcode三者)

本文详细介绍了Java的运行原理,包括JVM、类加载器、双亲委派机制,以及内存管理中的堆、栈和方法区。Java程序通过JDK中的JVM将字节码转换为特定平台的机器码执行。类加载过程包括装载、链接和初始化。在内存管理中,堆用于存放对象,栈存放基本类型和引用,方法区存储类和静态变量。此外,还讨论了==、equals和hashcode的区别和使用场景。
摘要由CSDN通过智能技术生成

JAVA基础笔记1

JAVA运行原理

平时我们编程的话需要给电脑安装jdk运行环境,如果只是运行java程序的话只需要装jre就可以了,jdk中包含jre,jre中包含jvm(虚拟机)。在java中引入了虚拟机概念,即在机器和编译程序之间加入了一层抽象的虚拟机器。这台虚拟机器在任何平台上都是提供编译程序的一个共同接口。编译程序只需要面向虚拟机,生成虚拟机能够理解的代码,然后由解释器来将虚拟机代码转换成特定系统的机器码执行。在java中,这种供虚拟机理解的代码叫做字节码(ByteCode Class文件内容),它不面向任何特定的处理器,只面向虚拟机。每一种平台的解释器是不同的,但是实现的虚拟机是相同的。java原程序经过编译器编译后变成字节码,字节码由虚拟机解释执行,虚拟机将每一条要执行的字节码送给解释器,解释器将其翻译成特定机器上的机器码,然后在特定的机器上运行。

Java运行流程

  • .java文件 --> java编译器(预编译) --> .class文件(字节码文件给虚拟机执行的文件) --> 类加载器(ClassLoader JVM虚拟机) --> 字节码校验机(校验代码写的是否正确) --> 解释器(把校验没问题的代码告诉操作系统) --> 操作系统平台(接受到代码命令执行)。
  • 编译型:直接一次性编译,一般是操作系统,C语言,C++语言用编译型。
  • 解释型:一般是用于网页,网页对于速度要求不是很高,边执行边解释。

Java内存

  1. 堆:存放new的对象和数组。可以被所有的线程共享,不会存放别的对象引用。
  2. 栈:存放基本变量类型(会包含这个基本类型的具体数值)。引用对象的变量(会存放这个引用在堆里面的具体地址)。
  3. 方法区:可以被所有的线程共享。包含了所有的class和static变量。

JVM(虚拟机)

java虚拟机是Java Virtual Machine,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能模拟来实现的。
java中,类加载器把一个类装入java虚拟机需要三个步骤来完成:装载,链接,初始化,其中链接有分为校验,准备,解析过程。

  1. 装载:查找和导入.class文件。
  2. 链接:检查装入的.class文件的正确性,然后,java虚拟机为变量分配内存,设置默认值。
  3. 初始化:把符号引用变成直接引用。

类加载器(ClassLoader):加载class文件

JVM运行图
双亲委派机制:安全

  • APP --> EXC --> BOOT(最终执行)
  • Bootstrap ClassLoader:主要负责加载核心的类库(java.lang等),构造Extension ClassLoader和Appliction ClassLoader。
  • Extension ClassLoader:主要负责加载jre/lib/ext目录下的一些扩展jar。
  • Application ClassLoader:主要负责加载应用程序的主函数类。

步骤

  1. 类加载器收到类加载的请求。
  2. 将这个请求向上委托给父类加载器去完成,一折向上委托,直到启动类加载器。
  3. 启动加载器检查是否能够加载当前这个类,能加载就结束使用当前的加载器,否者抛出异常,通知子加载器进行加载(自定义类)。
  4. 重复步骤3
  5. 找不到就会报错:ClassNotFound

双亲委派机制工作原理:

  1. 如果一个类加载器收到了类加载的请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行。
  2. 如果父类的加载器还存在其父类加载器,则进一步向上委托,依次递归,最终会到达顶层的Bootstrap ClassLoader。(从这里就可以看出来,类加载请求都会先到达启动类加载器)。
  3. 如果父类加载器可以完成类加载任务,就成功返回,倘若无法完成任务,则委派给它的子加载器去加载(自定义类)。

双亲委派机制原理图

双亲委派机制的优势:避免类的重复加载。一旦一个类被父类加载器加载之后,就不会在被委派给子类进行加载。保护程序安全。

JAVA中 == 和 equals 和 hashcode

==:

  1. 基本数据类型:也可称为原始数据类型,byte,short,char,int,long,float,double,boolean他们之间的比较应该用双等号==,比较的是他们之间的值。
  2. 引用类型:类,接口,数组,当它们用==进行比较的时候,比较的是他们在内存中的存放地址,所以除非是同一个new出来的对象,他们的比较后的结果为true,否则比较后结果为false。对象是存放在堆中的,栈中存放的是对象的引用(地址)。

equals:

equals()方法是用来判断其他的对象是否和该对象相等。其在Object里面就有定义,所以任何一个对象都有equals()方法,就看该对象有没有重写equals()方法。

//Object里面equals()方法源码
public boolean equals(Object obj){
	return (this == obj);
}

很明显Object定义的是对两个对象的地址值进行比较的,像String,Math,Integer等,这些封装类在使用equals方法时,已经覆盖了Object类的equals方法。
当equals()方法被重写时,hashcode也需要被重写。按照hashcode()的方法来说相等的对象,hashcode一定相等。

hashcode:

如果你想查找一个集合中是否包含某个对象,就需要把这个集合遍历一遍查找出来,但是当集合中的对象元素多了起来查找就开始费劲了,所以哈希算法就出来了,把一个集合拆分出来,分成若干个存储区域(可以看成一个个桶),每个对象可以计算出一个哈希码,可以根据哈希码分组,每组对应某个存储区域,这样一个对象根据它的哈希码就可以分到不同的存储区域。

在这里插入图片描述

对于要比较对象多的元素就不需要遍历整个集合了,只需要计算出要查找对象的key的hashcode然后找到该hashcode对应的存储区域查找就可以了。
每个对象都有hashcode,一个对象也肯定有物理地址,对象的物理地址跟hash地址不一样,hashcode代表对象的地址说的是对象在hash表中的位置,物理地址说的是对象存放在内存中的地址
一般是先通过hashcode来比较,如果hashcode相等再来使用equals方法来比较两个对象是否相等。如果重写了equals方法,最好也重写hashcode,其实这是一条规范,如果不重写程序也可以运行,不过会有隐藏的bug。一般一个类的对象如果是存储在HashTable,HashSet,HashMap等散列存储结构中,那么重写equals方法最好也重写hashcode。
在这里插入图片描述
HashCode的存在主要是为了查找的快捷性,HashCode是用来在散列存储结构中确定对象的存储地址的(后半句说的用HashCode来代表对象就是在hash表中的位置)

HashCode和equals的关系

  1. hashcode是为了提高在散列结构存储中查找效率,在线性表中没有作用。
  2. equals重写的时候hashcode也要重写。
  3. 两个对象的equals如果相等那么hashcode也一定相等。
  4. 如果两个对象的hashcode相同,不代表两个对象就相同,只能说明这两对象在散列存储结构中,存放于同一个区域。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值