欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

jvm核心:hashcode&markword

程序员文章站 2022-03-11 09:13:22
哈希函数(散列函数)单向函数,反向运算无法完成任意长度输入,固定长度输出输入不变,输出就不会变常见:MD5加密+saltMD5的使用场景:消息摘要简介两个不同的报文难以生成相同的摘要。难以对指定的摘要生成一个报文,而可以由改报文反推算出该指定的摘要。对字符串进行加密验证密码是否正确为什么要MD5+salt,MD5有一种暴力破解的方式,被称之为“彩虹表”,可快速地根据哈希值破解各类密码,但是基本都是简单常见的密码...

哈希函数(散列函数)

  • 单向函数,反向运算无法完成
  • 任意长度输入,固定长度输出
  • 输入不变,输出就不会变
  • 常见: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

相关标签: Java 面试