jvm核心:hashcode&markword
哈希函数(散列函数)
- 单向函数,反向运算无法完成
- 任意长度输入,固定长度输出
- 输入不变,输出就不会变
- 常见:MD5加密+salt
MD5的使用场景:
-
消息摘要简介
-
两个不同的报文难以生成相同的摘要。
-
难以对指定的摘要生成一个报文,而可以由改报文反推算出该指定的摘要。
-
-
对字符串进行加密
-
验证密码是否正确
-
为什么要MD5+salt,MD5有一种暴力破解的方式,被称之为“彩虹表”,可快速地根据哈希值破解各类密码,但是基本都是简单常见的密码,为了防止被破解,加上了salt,也就是MD5加随机的字符串然后在产出MD5,这样就可以避免彩虹表的攻击了。
java中的哈希函数(Object.hashCode())
- 先来了解一下hash表,hashMap,hashSet底层都是hashMap,hash表存的是k v对,(也叫散列表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
优点:
-
速度快
-
重复率低
有一个数组,想要把对象存进去,求这个对象的hashCode,算出来一个值,然后让这个值对整个数组的长度取模,取模的值是多少就存在什么位置上,这样存储对于查找非常的方便,直接计算刚刚存进去的对象的hashCode的值,然后取模,就能找到对象的位置了,
如果有多个对象存在一个位置怎么办呢?
如果存储位置不够多,那就存储一个链表,找的时候先找到这个位置,在这个位置中找到链表,然后再比对是否和我要找的对象相同了
如果链表过长怎么办呢?
链表的长度达到8的时候,就会变成红黑树,依序查找
在hashMap中怎么查找的呢??
- 如果在同一存储位置有多个对象存储,是链表的形式,那么他们的hash取模的值是相同的因为在同一位置,首先调用对象的hashCode找到位置,然后在看这个对象和链表中的每一个对象进行equals,这里注意一点就是hashCode和equals都要被重写,否则就是找不到位置或者equals不到对象,找错。
看一小段代码(hashCode查找和equals)
public class Main{
public static void main(String[] args){
Person p1 = new Person("a",5);
Person p2 = new Person("a",5);
//因为他们指向的不是同一个对象
System.out.println(p1.equals(p2)); //false
System.out.println(p1 == p2); //false
//因为重写了equals方法,字符串的比对就是一样的
String s1 = new String("aa"),s2 = new String("aa");
System.out.println(s1.equals(s2)); //true
//比的是对象,但是都是new出来的新对象,不在同一位置,所以是false
String s1 = new String("aa"),s2 = new String("aa");
System.out.println(s1 == s2); //false
}
}
class Person{
private String name;
private int age;
public Person(String name, int age){
this.name = nema;
this.age = age;
}
public String getName(){
return name;
}
public String setName(String name){
this.name = name;
}
public String getAge(){
return age;
}
public String setName(String age){
this.age = age;
}
}
markword的作用:
一个问题:
hashCode是在java的头文件里存一份呢,还是在java对象调用的时候重新计算呢?
答案:
hash的值每次需要用的时候不需要重新计算,因为他已经在对象头中计算好了,new出来这个对象的时候就已经计算好了
对象在堆内存中的布局分为三部分
-
对象头
-
存储对象的属性内容
-
填充(站位的,因为JAVA虚拟机规范的,要求每一个对象的长度在64位机器上必须是8字节的整数倍,如果你对象的长度不够,那就补到8字节的整数倍)
对象的头就被称为markword(头占8个字节64位中,在不压缩的情况下),是Hotspot的实现,头里记录了那些信息呢?
-
class指针 (属于哪个class类的)
-
锁信息(锁升级就再markword中做标志)
-
hashCode(对象new出来是就算好的hashCode的值)
本文地址:https://blog.csdn.net/AlbenXie/article/details/107373077