当前位置: 移动技术网 > IT编程>开发语言>Java > jvm核心:hashcode&markword

jvm核心:hashcode&markword

2020年07月17日  | 移动技术网IT编程  | 我要评论

哈希函数(散列函数)

  • 单向函数,反向运算无法完成
  • 任意长度输入,固定长度输出
  • 输入不变,输出就不会变
  • 常见:MD5加密+salt

MD5的使用场景:

  • 消息摘要简介

    1. 两个不同的报文难以生成相同的摘要。

    2. 难以对指定的摘要生成一个报文,而可以由改报文反推算出该指定的摘要。

  • 对字符串进行加密

  • 验证密码是否正确

  • 为什么要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出来这个对象的时候就已经计算好了

对象在堆内存中的布局分为三部分

  1. 对象头

  2. 存储对象的属性内容

  3. 填充(站位的,因为JAVA虚拟机规范的,要求每一个对象的长度在64位机器上必须是8字节的整数倍,如果你对象的长度不够,那就补到8字节的整数倍)

对象的头就被称为markword(头占8个字节64位中,在不压缩的情况下),是Hotspot的实现,头里记录了那些信息呢?

  1. class指针 (属于哪个class类的)

  2. 锁信息(锁升级就再markword中做标志)

  3. hashCode(对象new出来是就算好的hashCode的值)

本文地址:https://blog.csdn.net/AlbenXie/article/details/107373077

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网