一 UUID.toString方法与Long.fastUUID方法的关联

  • UUID类
public final class UUID implements java.io.Serializable, Comparable<UUID> {

	 public static UUID randomUUID() {
SecureRandom ng = Holder.numberGenerator; byte[] randomBytes = new byte[16];
ng.nextBytes(randomBytes); // 真正生成随机数的地方
randomBytes[6] &= 0x0f; /* clear version */
randomBytes[6] |= 0x40; /* set to version 4 */
randomBytes[8] &= 0x3f; /* clear variant */
randomBytes[8] |= 0x80; /* set to IETF variant */
return new UUID(randomBytes);
} /*
* The random number generator used by this class to create random
* based UUIDs. In a holder class to defer initialization until needed.
*/
private static class Holder {
static final SecureRandom numberGenerator = new SecureRandom();
} /*
* The most significant 64 bits of this UUID.
* @serial
*/
private final long mostSigBits; /*
* The least significant 64 bits of this UUID.
* @serial
*/
private final long leastSigBits; private UUID(byte[] data) {
long msb = 0;
long lsb = 0;
assert data.length == 16 : "data must be 16 bytes in length";
// long的64位: 8位 8位 8位 8位 8位 8位 8位 8位 8位
// 简单说:msb = data[0] ...... ...... data[7]
for (int i=0; i<8; i++)
msb = (msb << 8) | (data[i] & 0xff);
// long的64位: 8位 8位 8位 8位 8位 8位 8位 8位 8位
// 简单说:lsb = data[8] ...... ...... data[15]
for (int i=8; i<16; i++)
lsb = (lsb << 8) | (data[i] & 0xff);
this.mostSigBits = msb;
this.leastSigBits = lsb;
} // SharedSecrets javaLangAccess变量什么时候设置进去?
// 答案是System
private static final JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); public String toString() {
return jla.fastUUID(leastSigBits, mostSigBits);// 实际调用了Long.fastUUID方法
}
} public final class System {
/**
* Initialize the system class. Called after thread initialization.
*/
private static void initPhase1() {
// ...
setJavaLangAccess();
// ...
} private static void setJavaLangAccess() {
// Allow privileged classes outside of java.lang
// 匿名内部类注册
SharedSecrets.setJavaLangAccess(new JavaLangAccess() {
// ......
public String fastUUID(long lsb, long msb) {
return Long.fastUUID(lsb, msb);
}
});
}
} public final class Long extends Number implements Comparable<Long> { // 其实就是提供UUID的toString方法.......
static String fastUUID(long lsb, long msb) {
if (COMPACT_STRINGS) {
byte[] buf = new byte[36];
formatUnsignedLong0(lsb, 4, buf, 24, 12);
formatUnsignedLong0(lsb >>> 48, 4, buf, 19, 4);
formatUnsignedLong0(msb, 4, buf, 14, 4);
formatUnsignedLong0(msb >>> 16, 4, buf, 9, 4);
formatUnsignedLong0(msb >>> 32, 4, buf, 0, 8); buf[23] = '-';
buf[18] = '-';
buf[13] = '-';
buf[8] = '-'; return new String(buf, LATIN1);
} else {
byte[] buf = new byte[72]; formatUnsignedLong0UTF16(lsb, 4, buf, 24, 12);
formatUnsignedLong0UTF16(lsb >>> 48, 4, buf, 19, 4);
formatUnsignedLong0UTF16(msb, 4, buf, 14, 4);
formatUnsignedLong0UTF16(msb >>> 16, 4, buf, 9, 4);
formatUnsignedLong0UTF16(msb >>> 32, 4, buf, 0, 8); StringUTF16.putChar(buf, 23, '-');
StringUTF16.putChar(buf, 18, '-');
StringUTF16.putChar(buf, 13, '-');
StringUTF16.putChar(buf, 8, '-'); return new String(buf, UTF16);
}
}
}
  • UUID的组成部分

参考:http://www.ietf.org/rfc/rfc4122.txt

UUID  = time-low "-" time-mid "-" time-high-and-version "-" clock-seq-and-reserved clock-seq-low "-" node
time-low = 4hexOctet
time-mid = 2hexOctet
time-high-and-version = 2hexOctet
clock-seq-and-reserved = hexOctet
clock-seq-low = hexOctet
node = 6hexOctet
hexOctet = hexDigit hexDigit
hexDigit =
"0" / "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9" /
"a" / "b" / "c" / "d" / "e" / "f" /
"A" / "B" / "C" / "D" / "E" / "F"

二 Java加密体系结构(JCA)

参考:https://blog.csdn.net/u012741741/article/details/79209984

这篇译文很好,不过本文不是为了讲解加密体系,所以尽量只获取最少的额外知识点来完成UUID.randomUUID的剖析

1 介绍

  • JAVA平台强调安全性,包含内容很多如:语言安全,密码学,公钥基础设施,认证,安全通信和访问控制。
  • JCA是JAVA平台的一部分,提供一个“Provider”体系结构和一组用于数字签名,消息摘要(哈希),证书和证书验证,加密(对称/非对称块/流密码),密钥生成管理和安全随机数生成等等。有了这些API,开发人员可以轻松将安全性集成到自己的应用中。
  • JCA设计原则:
    • 实现独立性:应用程序不需要自己实现安全性,它们可以从Java平台请求安全服务。
    • 实现互操作性:Provider不需要绑定到固定的应用中,应用也不需要绑定特定的Provider
    • 算法可拓展性: Java平台包含许多内置的Provider,这些Provider实现了当今广泛使用的一组基本的安全服务 。但也许有些应用希望集成新兴的算法

2 UUID中涉及JCA的类

  • SecureRandom:它是一个随机数生成器(RNG),同时是JCA中的其中一个引擎类。引擎类为特定类型的密码服务提供接口,而不依赖于特定的密码算法或提供者。
  • SecureRandomSpi:该类定义了SecureRandom的服务提供者接口(SPI),意味着为SecureRandom提供具体实现的生成器需要实现该类的所有方法。
  • DRBG:它实现了"SecureRandom.DRBG"算法,是SecureRandom的其中一个随机数生成器实现。
  • Provider:该类表示Java安全API的“提供者”,其中某个具体提供者需要实现Java安全的部分或全部部分。
  • Sun:Sun的安全提供者,Provider的子类。
  • Provider.Service:Provider的内部类,封装SPI的具体实现类,通过Service能够找到具体的实现类

3 SecureRandom的具体实现类追寻

(1)找出Jdk中有许多Providers,许多官方的,或者第三方添加。如:Sun、SunJCE、JdkLDAP、XMLLDSig等

(2)顺序遍历Providers并解析Providers中提供的算法为Services,如:

  • SecureRandom.DRBG -> sun.security.provider.DRBG
  • MessageDigest.SHA -> sun.security.provider.SHA
  • Alg.Alias.KeyPairGenerator.1.2.8400.10040.4.1 -> DSA
  • Alg.Alias.CertificateFactory.X509 -> X.509
  • Provider.id info -> SUN(DSA key/parameter generation; DSA signing; SHA-1 , MD5...)
  • .....

(3)发现DRBG是SecureRandom的具体提供者

(4)根据DRBG的全类名创建对象并返回使用

4 通过代码跟踪看看

public class SecureRandom extends java.util.Random {

    public SecureRandom() {
super(0);
getDefaultPRNG(false, null);
this.threadSafe = getThreadSafe();
} private void getDefaultPRNG(boolean setSeed, byte[] seed) {
String prng = getPrngAlgorithm(); // 返回"DRBG"
if (prng == null) {
prng = "SHA1PRNG";
this.secureRandomSpi = new sun.security.provider.SecureRandom();
this.provider = Providers.getSunProvider();
if (setSeed) this.secureRandomSpi.engineSetSeed(seed);
} else {
try {
SecureRandom random = SecureRandom.getInstance(prng);
this.secureRandomSpi = random.getSecureRandomSpi();
this.provider = random.getProvider();
if (setSeed) {
this.secureRandomSpi.engineSetSeed(seed);
}
} catch (NoSuchAlgorithmException nsae) {
throw new RuntimeException(nsae);
}
}
if (getClass() == SecureRandom.class) {
this.algorithm = prng;
}
} private static String getPrngAlgorithm() {
for (Provider p : Providers.getProviderList().providers()) {
for (Service s : p.getServices()) {
if (s.getType().equals("SecureRandom")) return s.getAlgorithm();
}
}
return null;
} public static SecureRandom getInstance(String algorithm) throws NoSuchAlgorithmException {
Instance instance = GetInstance.getInstance("SecureRandom",
SecureRandomSpi.class,
algorithm);
return new SecureRandom((SecureRandomSpi)instance.impl,
instance.provider, algorithm);
}
} public class GetInstance {
public static Instance getInstance(String type, Class<?> clazz,
String algorithm) throws NoSuchAlgorithmException {
ProviderList list = Providers.getProviderList();
Service firstService = list.getService(type, algorithm);
return getInstance(firstService, clazz);
} public static Instance getInstance(Service s, Class<?> clazz)
throws NoSuchAlgorithmException {
Object instance = s.newInstance(null);
return new Instance(s.getProvider(), instance);
}
} public class Provider{ public class Service{
public Object newInstance(Object constructorParameter)
throws NoSuchAlgorithmException {
Class<?> ctrParamClz;
EngineDescription cap = knownEngines.get(type);
if (cap == null) {
ctrParamClz = constructorParameter == null?
null : constructorParameter.getClass();
} else {
ctrParamClz = cap.constructorParameterClassName == null?
null : Class.forName(cap.constructorParameterClassName);
}
return newInstanceUtil(getImplClass(), ctrParamClz, constructorParameter);
} // 返回class sun.security.provider.DRBG
// return the implementation Class object for this service
private Class<?> getImplClass() throws NoSuchAlgorithmException {
Reference<Class<?>> ref = classRef;
Class<?> clazz = (ref == null) ? null : ref.get();
ClassLoader cl = provider.getClass().getClassLoader();
if (cl == null) {
clazz = Class.forName(className);//className为sun.security.provider.DRBG
} else {
clazz = cl.loadClass(className);
}
classRef = new WeakReference<>(clazz);
return clazz;
}
} private static Object newInstanceUtil(final Class<?> clazz,
final Class<?> ctrParamClz, final Object ctorParamObj)
throws Exception {
if (ctrParamClz == null) {
Constructor<?> con = clazz.getConstructor();
// 最后就是构造器的newInstance
return con.newInstance();
} else {
Constructor<?> con = clazz.getConstructor(ctrParamClz);
return con.newInstance(ctorParamObj);
}
}
}

补充第11期作业:Long.fastUUID与UUID.toString之间的关系的更多相关文章

  1. day 11课后作业

    # -*- coding: utf-8 -*-# @Time : 2019/1/3 20:03# @Author : Endless-cloud# @Site : # @File : day 11 课 ...

  2. C语言程序设计第11次作业

    一.本次课主要内容: 本章主要介绍指针相关的基础知识,本节课的主要如下 (1)通过示例"密码开锁"引入指针的概念和主要知识点,分析了密码开锁的过程来说明变量.内存单元和地址之间的关 ...

  3. 《HelloGitHub月刊》第11期

    <HelloGitHub>第11期 兴趣是最好的老师,<HelloGitHub>就是帮你找到兴趣! 简介 最开始我只是想把自己在浏览 GitHub 过程中,发现的有意思.高质量 ...

  4. 《HelloGitHub月刊》第 11 期

    <HelloGitHub>第 11 期 兴趣是最好的老师,<HelloGitHub>就是帮你找到兴趣! 简介 最开始我只是想把自己在浏览 GitHub 过程中,发现的有意思.高 ...

  5. python 全栈开发,Day43(python全栈11期月考题)

    python全栈11期月考题 1.常用字符串格式化有哪些?并说明他们的区别 2.请手写一个单例模式(面试题) 3.利用 python 打印前一天的本地时间,格式为‘2018-01-30’(面试题) 4 ...

  6. 201621123062《java程序设计》第11周作业总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. 思维导图: 2. 书面作业 本次PTA作业题集多线程 2.1. 源代码阅读:多线程程序BounceThread 2 ...

  7. 201621123018《java程序设计》第11周作业总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. 2. 书面作业 本次PTA作业题集多线程 1. 源代码阅读:多线程程序BounceThread 1.1 BallR ...

  8. Facebook不相信所谓的员工能力等级。《长效商业英雄》(《哈佛商业评论》2016年11期),4星。

    老牌管理杂志.本期我给4星.以下是书中一些信息的摘抄: 1:爱因斯坦曾说:“任何傻瓜都能让事情更复杂,只有天才能让事情变简单.”单就这一点来看,乔布斯无疑是天才中的天才.#137 2:通过让苹果聚焦于 ...

  9. 史航416第11次作业&总结

    作业1:冒泡排序 #include <stdio.h> ],int n); int main() { ],n,i; printf("输入一个整数n:"); scanf( ...

随机推荐

  1. Gokit微服务-服务链路追踪

    https://mp.weixin.qq.com/s/gjKOy4SDpsjUXDC3Q1YdFw Gokit微服务-服务链路追踪 原创: 兮一昂吧 兮一昂吧 2月28日

  2. CXF框架构建和开发 Services

    Apache CXF 是一个开源的 Services 框架,CXF 帮助您来构建和开发 Services 这些 Services 可以支持多种协议,比如:SOAP.POST/HTTP.RESTful ...

  3. PCA人脸识别学习笔记---原理篇

     前言 在PCA人脸识别中我们把一个人脸图片看做一个特征向量,PCA做的事情就是:找到这样一组基向量来表示已有的数据点,不仅仅是将高维度数据变成低维度数据,更能够找到最关键信息. 假设已有数据{xi} ...

  4. Flask中路由参数

    Flask中路由参数.请求方式设置 一.参数设置 1.参数类型 Flask中参数的使用 @app.route('/parames/<username>/') def hello_world ...

  5. [Scikit-learn] 1.5 Generalized Linear Models - SGD for Regression

    梯度下降 一.亲手实现“梯度下降” 以下内容其实就是<手动实现简单的梯度下降>. 神经网络的实践笔记,主要包括: Logistic分类函数 反向传播相关内容 Link: http://pe ...

  6. python3 super().__init__() 和 __init__() 的区别

    1.单继承 super().__int__()和 Base.__init__(self)是一样的, super()避免了基类的显式调用. class Base(object): def __init_ ...

  7. vue+大文件断点续传

    根据部门的业务需求,需要在网络状态不良的情况下上传很大的文件(1G+).其中会遇到的问题:1,文件过大,超出服务端的请求大小限制:2,请求时间过长,请求超时:3,传输中断,必须重新上传导致前功尽弃.解 ...

  8. windows下redis配置密码

    redis安装后目录如下: 最简单的启动方式是直接双击redis-server.exe 如果要设置密码,首先打开配置文件,要注意的是这两个都是配置文件,记住你改的是哪一个,不放心的可以两个都改. 然后 ...

  9. VICA概述及架构设计

    VICA全称VAT Invoice Client Platform(增值税发票客户端平台),顾名思义就是公司增值税发票业务相关处理的客户端集成平台.在VICA出现之前,公司发票开具的技术主要是依赖于A ...

  10. 微信小程序 仿‘得到app’分类列表页

    今天另起一篇,贴出完整的代码,大概思路是左侧大分类列表,点击后联动右侧二级分类,及下面文章列表,点击二级分类也联动下面文章列表. 代码如下: <view class="page&quo ...