在上一篇文章JVM是如何与操作系统交互的中,我们介绍了CPU是如何与JVM去交互完成一个main方法的执行的。
那么在上篇文章中所提到的JVM虚拟机中的那一块内存区域是什么样的呢?
CPU是从JVM中的什么位置获取到了什么样的指令呢?带着以上问题,我们来了解一下什么是JVM内存模型
由上图可以看到所有线程共享的区域为堆和方法区两部分,而程序计数器、栈和本地方法栈则为每个线程私有的内存区域。
对于Java应用来讲,堆是虚拟机所管理的内存中最大的一块,该区域被所有线程共享,在虚拟机启动时创建,几乎所有的Java对象实例都存放在该区域。
该区域也是垃圾收集器所管理的区域,由于G1垃圾收集器之前的大部分垃圾收集器都是基于分代理论设计的,所以从内存回收的角度来看的话,该区域有新生代、老年代、永久代。从分配内存的角度来看的话,堆中可以有多个线程私有的分配缓冲区,用于提升对象分配的效率。
无论从什么角度来看,最终的目的都是为了能更好的分配内存和回收内存。当对象在该区域无法完成内存空间的分配,并且堆空间也无法再扩展时,抛出OOM异常。
方法区也是一块被各个线程共享的内存区域,用于存储已经被虚拟机加载的类型信息、常量、静态变量、即时编译后的代码缓存数据等,该区域基本不发生垃圾收集的行为,即使发生垃圾收集,收益也很小。
当该区域无法满足新的内存分配需求时,抛出OOM异常。
程序计数器是一块线程私有的内存空间,因为多线程是通过线程轮流切换、分配处理器的执行时间来实现的,所以在任何一个具体的时刻,处理器的一个内核都只会执行一条线程中的指令,为了让线程切换后能恢复到正确的执行位置,所以每条线程都会由一个独立的程序计数器,各个线程之间的计数器独立存储,互不影响。当线程在执行Java方法时,记录着正在执行的虚拟机字节码的指令地址;执行Native方法时,该计数器为Undefined。该区域不会抛出OOM异常。
和程序计数器一样,栈也是线程私有的一块内存空间,也可以叫做Java方法执行的线程内存模型,每个方法被执行时,都会同步创建一个栈帧,用于存储局部变量表、操作数栈、方法出口等信息。每个方法从被调用到执行完毕就对应着一个栈帧在虚拟机栈中的入栈和出栈的过程。
一个线程中的方法调用链可能会很长,以Java程序的角度来看,同一时刻、同一条线程里面,在 调用堆栈的所有方法都同时处于执行状态。而对于执行引擎来讲,在活动线程中,只有位于栈顶的方法才是在运行的,只有位于栈顶的栈帧才是生效的,其被称为“当前栈帧”(Current Stack Frame),与 这个栈帧所关联的方法被称为“当前方法”(Current Method)。执行引擎所运行的所有字节码指令都只针对当前栈帧进行操作。
该内存区域异常情况:当线程请求的栈深度大于虚拟机所允许的栈深度时,抛出StackOverflowError异常;如果Java虚拟机允许动态扩展,当栈扩展时无法申请到足够的内存时,抛出OOM异常。
本地方法栈与虚拟机栈作用相似,区别为本地方法栈服务于Native方法。
当class
文件被加载进虚拟机后,类信息会存放在方法区,在实际运行的时候会执行方法区中的代码,在JVM
中所有的线程共享堆内存和方法区,而每个线程有自己独立的Java方法栈,本地方法栈(面向native方法),PC寄存器(存放线程执行位置),当调用一个方法的时候,Java虚拟机会在当前线程对应的方法栈中压入一个栈帧,用来存放Java字节码操作数以及局部变量,这个方法执行完会弹出栈帧,一个线程会连续执行多个方法,对应不同的栈帧的压入和弹出,压入栈帧后就是JVM解释执行的过程了。
本作品系原创,采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,转载请注明出处。
在之前的文章,我们介绍了类加载的过程以及类加载器和双亲委派模型
那么我们的应用程序被加载到JVM中之后,操作系统是如何去与JVM虚拟机交互来执行我们应用程序中的逻辑的呢?
答案就是大名鼎鼎的CPU,全称是Central Processing Unit
,也就是中央处理器。
那么CPU在操作系统中起到了什么样的作用呢?
CPU由主要由控制器和运算器两部分组成。
非常的枯燥无味,说人话就是:CPU会根据程序计数器所指示的位置,从主存中取出数据,寄存至数据寄存器,然后CPU从数据寄存器中取出指令,放入指令寄存器,并对指令译码。将指令分解成一系列的微操作,然后发出控制命令,执行这一系列微操作,从而完成一条指令的执行。
在前面的文章中我们说过,Java的跨平台的特性是基于JVM虚拟机能够将Java代码编译后的字节码(.class)文件转译为对应的机器所能识别的机器码。
1 | public class ByteCodeTest { |
通过javac
编译后使用javap -verbose
命令即可查看到该类的字节码
以下是System.out.println("Hello world")
的对应的字节码
1 | 0: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream; |
虚拟机将以上字节码通过解释器解释成汇编指令,最终由硬件转译为CPU能识别的机器指令。
java
命令执行后,虚拟机启动,将class文件加载到虚拟机由于该类包含了main方法,JVM类加载机制在之前的文章JVM中类加载的过程中的初始化
部分中讲过,包含main方法的类,会在虚拟机启动时过程中触发初始化
的动作,那么该类中的信息就会被我们按照JVM内存模型的规则存入相对应的内存区域java
命令执行后,相当于在操作系统中启动了一个JVM进程,虚拟机启动,将class文件通过类装载器加载到虚拟机的内存区域,然后通过JVM通过Java解释器和JIT编译器两者相结合的方式,将字节码解释为汇编语言(对应操作系统的相关函数),等待被调用。
本作品系原创,采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,转载请注明出处。
在上文JVM-类加载机制中,描述了在
java
命令执行后,JVM类加载的整个流程。
- 在上文中可以看到ClassLoader在
java
命令执行后起到了承上启下的重要作用- 那么JVM中的ClassLoader是如何运行的呢?本文将带你揭开它神秘的面纱
虚拟机的设计团队把类加载阶段中的通过类的全限定名去找到对应的Class文件
这个动作放到Java虚拟机的外部去实现,为了便于让应用程序自己决定如何去获取所需要的类,实现这个动作的代码模块就叫做“类加载器”。
类加载器只用于类的加载动作,但是在我们的Java程序中起到的作用却不至于类的加载。在我们比较两个类是否相等时(equals()
、isInstance()
、关键字instanceof
),即使两个类来源于同一个Class文件,被同一个虚拟机加载,当它们的类加载不同时,那么这两个类也会不相等。
1 | package com.imchenway.classload; |
输出:
1 | class com.imchenway.classload.ClassLoaderTest |
由此可以看到,ClassLoaderTest
在启动时由jdk.internal.loader.ClassLoaders$AppClassLoader@55054057
所加载,而obj
由com.imchenway.classload.ClassLoaderTest$1@6ff3c5b5
所加载,所以System.out.println(obj instanceof com.imchenway.classload.ClassLoaderTest);
这一行输出的结果为false
,因为类的唯一性由是否是同一个类加载器和是否同一个字节码文件同时决定的。
java.lang.ClassLoader
。<JAVA_HOME>\lib
目录中的,或者被XbootClasspath
参数指定路径的类库加载到虚拟机内存中。<JAVA_HOME>\lib\ext
目录中的,或者被java.ext.dirs
系统变量所指定的类库。当一个类加载器收到了类加载的请求时,首先是交给自己的父类加载器去加载,最终都会到达顶层的引导类加载器,当父类加载器反馈无法完成这个加载请求时,子加载器尝试自己去加载。
在类与类加载器的关系中我们证明了一个类的唯一性由加载这个类的类加载器和类本身所决定,如果没有双亲委派机制存在的话,设想如果应⽤程序类加载器想要 加载⼀个有破坏性的
java.lang.System
类,双亲委派模型会⼀层层向上委派,最终委派给启动类加载器,而启动类加载器中检查到缓存中已经有了这个类,并不会再加载这个有破坏性的System类。
当然,实际上自定义包名java
开头的类将无法加载成功
1 | protected Class<?> loadClass(String name, boolean resolve) |
findLoadedClass(name);
判断该类是否已经加载,如果加载过,则使用缓存loadClass(String name, boolean resolve)
方法findBootstrapClassOrNull(name)
中调用本地方法(C++实现)通过类的全限定名去找到对应的Class文件
,同时通过类加载器的唯一实例对象地址和字节码文件的相同来判定类的唯一性,正时因为这个特性,也让类加载机制可以拥有隔离性。破坏双亲委托模型,只需要在loadClass(String name, boolean resolve)
方法中,不调用父类加载器去加载类就可以了。
由于类的唯一性由是否是同一个类加载器和是否同一个字节码文件同时决定的
这一特性,可以为应用程序提供类库的隔离性。
CommonClassLoader能加载的类都可以被
Catalina ClassLoader
和SharedClassLoader
使用,从而实现了公有类库的共用,而CatalinaClassLoader
和Shared ClassLoader
自己能加载的类则与对方相互隔离。
WebAppClassLoader可以使用SharedClassLoader
加载到的类,但各个WebAppClassLoader
实例之间相互隔离。
本作品系原创,采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,转载请注明出处。
众所周知,Java的slogan就是”Write once, run anywhere.”,这也就意味着无论我们在什么平台的机器上用Java去做实现,都可以在任何支持Java的系统上直接运行,无需做任何额外操作。
Java是如何做到这些的呢?答案是JRE。
- 那么什么是JRE?为什么叫JRE?
- JRE(Java Runtime Environment),是一个Java代码的运行时环境,属于软件层,运行在操作系统软件之上,属于JDK的一部分。
- 什么是JDK?
- JDK(Java Development Kit),每一个JDK都包含了一个兼容的JRE和一个JVM,并且JDK包含了许多Java开发人员常用的工具以及类库,比如
javac、java、jar、jmap、jstat、jstack、jinfo、rt.jar
等。- 什么是JVM?
- JVM(Java Virtual Machine),JVM可以理解为是一个运行在操作系统之上的虚拟电脑,当我们通过
javac
将*.java
编译成JVM可识别*.class
字节码文件后,再执行java
,此时JVM会将*.class
字节码文件解释成当前操作系统平台可识别的机器码去执行。这样的话就实现了”Write once, run anywhere.”。- 整体流程如下所示
java.lang.Class
对象,作为方法区中这个类中的各种数据结构的访问入口java.lang.Object
外,所有的类都必须有父类)1 | public static int value = 99; |
<clinit>()
至此,一个字节码文件便已经初始化完成。
加载一个class类的过程总体分三个步骤,加载、链接、初始化
,其中链接阶段分为验证、准备、解析
三个阶段,加载阶段通过类的全限定名来读取class字节码文件的二进制流,并将字节码数据转化为方法区的运行时数据结构。链接阶段中的验证阶段对字节码文件进行格式和安全校验,准备阶段为类中的部分变量(被static修饰的变量)分配内存和初始值的赋值,解析阶段将常量池中的符号引用替换为直接引用。初始化阶段会将静态代码的赋值操作和静态代码块中的代码交给<clinit>()
方法进行初始化,完成变量的赋值以及资源的分配。
本作品系原创,采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,转载请注明出处。
Launchd是 MacOS 用来管理系统和用户级别的守护进程的工具。
该工具由两部分组成:
/System/Library/LaunchDaemons
和/Library/LaunchDaemons
中的所有plist 文件,然后根据需要启动 launchctl。launchctl
中。/System/Library/LaunchDaemons
和/Library/LaunchDaemons
中的所有 plist 文件并加载它们/System/Library/LaunchAgents
、/Library/LaunchAgents
、~/Library/LaunchAgents
这三个目录的文件并加载它们RunAtLoad
为true
或KeepAlive
为true
时,会在加载时立即执行plist 示例:
1 |
|
类型 | 位置 | 以什么用户权限运行 | 运行时机 |
---|---|---|---|
系统 Daemons | /System/Library/LaunchDaemons | root/指定用户 | 开机时 |
全局 Daemons | /Library/LaunchAgents | root/指定用户 | 开机时 |
系统 Agents | /System/Library/LaunchAgents | 当前登录用户 | 用户登录 |
全局 Agents | /Library/LaunchAgents | 当前登录用户 | 用户登录 |
用户 Agents | ~/Library/LaunchAgents | 当前登录用户 | 当前设置用户登录时 |
LaunchDaemons
和LaunchAgents
主要有以下两个区别:
LaunchDaemons
在按下开机按钮后,用户还未输入密码时,就已经运行了。LaunchAgents
在用户输入密码后,才开始运行。LaunchDaemons
是以 root/其他指定用户运行LaunchAgents
是以当前登录用户的权限运行下面通过实现定时开关 Mac 的 Wi-Fi 来演示具体流程:
如果有多台 Mac 同步需求,建议将以下 shell 放入自己的 iCloud 目录,没有这个需求的话自行安排,记得存放路径就行
1 | !/bin/sh |
1 | !/bin/sh |
/Library/LaunchAgents
下,这样只要电脑开机,就算未输入密码,plist 文件也会被执行到Label
标签的值,不能与其他 plist 文件中的Label
标签中的值完全重复ProgramArguments
标签中放入 shell 所在的路径StartCalendarInterval
用于控制在指定的时间执行 shellStartCalendarInterval
替换为每隔 N 秒执行一次 shellRunAtLoad
和KeepAlive
为true
时,在 plist 被加载时,会被立即执行一次StandardOutPath
填写脚本运行日志输出的路径StandardErrorPath
填写脚本运行错误日志输出的路径1 |
|
1 |
|
launchctl list
列出已加载的所有 plist
其中 PID 为-
的表示虽然已加载,但是未启动,PID 为数字的表示已启动并且这个数字就时它的 PID
launchctl load
launchctl load /Library/LaunchDaemons/closewifi.plist
手动加载一个 plist 任务
launchctl unload
launchctl unload /Library/LaunchDaemons/closewifi.plist
禁用一个 plist 任务
launchctl start
启动一个 plist 任务
launchctl stop
停止一个 plist 任务
A launchd Tutorial
launchctl
Daemons and Services Programming Guide
man launchd.plist
本作品系原创,采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,转载请注明出处。
Bypass proxy settings for these Hosts & Domains:
中填入内网IP127.0.0.1:1087
proxy -> external proxy settings
proxy -> external proxy settings
ByPass external proxies for the following hosts:
中填入内网ipMap Remote...
keychain
处将新安装的证书设置为永久信任
本作品系原创,采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,转载请注明出处。
我们重启macbook,在开机的时候按command+R进入恢复模式,然后我们在终端输入
csrutil disable
当我们设置完分辨率后可以再输入以下命令打开,保证安全性。
csrutil enable
sudo defaults write /Library/Preferences/com.apple.windowserver DisplayResolutionEnabled -bool YES
ioreg -l | grep "DisplayVendorID"
ioreg -l | grep "DisplayProductID"
如图:
文件中添加了几个例子。
如图:
然后我们把这个文件夹拷贝到/System/Library/Displays/Contents/Resources/Overrides/中去
重启系统打开RDM,这就可以进行切换了。
如图:
sudo mount -uw /
本作品系原创,采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,转载请注明出处。
1 | # socks5协议,1080端口修改成自己的本地代理端口 |
1 | # socks5协议,1080端口修改成自己的本地代理端口 |
1 | # 查看所有配置 |
1 | 151.101.72.249 github.http://global.ssl.fastly.net |
本作品系原创,采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,转载请注明出处。
""
#1 | 搜索: "测试搜索" |
-
#1 | 例如:搜索 -引擎 |
*
#1 | 搜索:搜索*擎 |
or
#1 | baidu or Google |
~
#1 | 浙江 ~大学 |
1 | 搜索:inurl:搜索引擎优化 |
1 | 搜索 :inanchor:点击这里 |
intitle
#1 | 例如:intitle:面向对象 |
1 | 搜索 :allintitle:SEO 搜索引擎优化 |
1 | allinurl:SEO 搜索引擎优化 |
1 | related: youtube.com |
site
#1 | java site:baidu.com |
1 | site:.com java |
1 | filetype:pdf java |
1 | 54磅=?公斤 |
1 | Answers:直接让你的搜索需求面向专业人员的小组 |
1 | Ctrl+F |
1 | Ctrl + +/- |
1 | Ctrl + L |
1 | weather/time/sunrise/sundown+城市名(英文) |
1 | 歌手名字(英语)+music/songs |
1 | 1美元 in 人民币 |
1 | hangzhou to jiangxi distance |
本作品系原创,采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,转载请注明出处。
- 两数相加:
- 给出两个
非空
的链表用来表示两个非负的整数。其中,它们各自的位数是按照逆序
的方式存储的,并且它们的每个节点只能存储一位
数字。- 如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
- 您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
- 示例:
- 输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
- 输出:7 -> 0 -> 8
- 原因:342 + 465 = 807
(2 -> 3 -> 4) + (5 -> 6-> 7)
时,结果应该是 234 + 567 = 801
,输出 8 -> 0 -> 1
;234
和567
取出后再放入链表输出即可;(9 -> 9 -> 9 -> 9 -> 9 -> 9 -> 9 -> 9 -> 9 -> 9 -> 9 -> 9 -> 9 -> 9 -> 9 -> 9 -> 9 -> 9) + (5 -> 6-> 7)
的极限测试,将取出的234
和567
相加时会抛出整数溢出异常,用BigDicimal
也无解,况且实际情况中无法知道该数会有多大,放弃。(2 -> 3 -> 4) + (5 -> 6-> 7)
时,其实应该是 432 + 765 = 1197
,输出 7 -> 9 -> 1 -> 1
;1 | private static ListNode addTwoNumbers(ListNode l1, ListNode l2) { |
ListNode result = dummyHead;
将dummyHead
和result
指向同一个引用;result = result.next;
只是在该引用后添加新的节点;return dummyHead.next;
返回的是有效的第一个节点;
本作品系原创,采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,转载请注明出处。
node.js
git
npm
1 | npm install -g hexo-cli |
1 | hexo init imchenway.com |
1 | . |
server
的缩写,浏览器输入就可以预览效果了。#1 | hexo s |
1 | git clone https://github.com/imchenway/imchenway.github.io.git |
1 | cd username.github.io |
1 | git add --all |
cd ~/.ssh
cat ~/.ssh/id_rsa.pub
命令查看本机上的SSH key
1 | git config --global user.name "用户名" |
1 | ssh-keygen -t rsa -C '上面的邮箱' |
ssh key
。cat ~/.ssh/id_rsa.pub
查看 ~/.ssh/id_rsa.pub
文件内容,获取到你的SSH key
1 | ssh -T git@github.com |
imchenway.com
下,修改_config.yml
中的deploy配置#1 | cd imchenway.com |
1 | npm install hexo-deployer-git --save |
1 | hexo g -d |
1 | hexo new '博文标题' |
1 | hexo g |
1 | hexo clean |
1 | cd imchenway.com |
_config.yml
#1 | # anatole |
1 | hexo clean |
1 | npm install hexo-git-backup --save |
_config.yml
,添加如下内容1 | # theme:你要备份的主题名称 |
hexo
1 | hexo backup |
1 | git clone https://github.com/imchenway/imchenway.github.io.git |
1 | npm install hexo-toc --save |
_config.yml
1 | toc: |
1 | <!-- toc --> |
/source/css/
目录中的.scss
文件里面的text-transform: uppercase;
全去掉打开hexo/themes/anatole/layout/partial/comments.pug
文件, 在文件末尾加入以下代码:
1 | if theme.gitalk |
在 /hexo/themes/anatole/source/js
目录中新建文件 md5.min.js
, 在其中加入如下内容:
1 | md5.min.js!function(n){"use strict";function t(n,t){var r=(65535&n)+(65535&t);return(n>>16)+(t>>16)+(r>>16)<<16|65535&r}function r(n,t){return n<<t|n>>>32-t}function e(n,e,o,u,c,f){return t(r(t(t(e,n),t(u,f)),c),o)}function o(n,t,r,o,u,c,f){return e(t&r|~t&o,n,t,u,c,f)}function u(n,t,r,o,u,c,f){return e(t&o|r&~o,n,t,u,c,f)}function c(n,t,r,o,u,c,f){return e(t^r^o,n,t,u,c,f)}function f(n,t,r,o,u,c,f){return e(r^(t|~o),n,t,u,c,f)}function i(n,r){n[r>>5]|=128<<r%32,n[14+(r+64>>>9<<4)]=r;var e,i,a,d,h,l=1732584193,g=-271733879,v=-1732584194,m=271733878;for(e=0;e<n.length;e+=16)i=l,a=g,d=v,h=m,g=f(g=f(g=f(g=f(g=c(g=c(g=c(g=c(g=u(g=u(g=u(g=u(g=o(g=o(g=o(g=o(g,v=o(v,m=o(m,l=o(l,g,v,m,n[e],7,-680876936),g,v,n[e+1],12,-389564586),l,g,n[e+2],17,606105819),m,l,n[e+3],22,-1044525330),v=o(v,m=o(m,l=o(l,g,v,m,n[e+4],7,-176418897),g,v,n[e+5],12,1200080426),l,g,n[e+6],17,-1473231341),m,l,n[e+7],22,-45705983),v=o(v,m=o(m,l=o(l,g,v,m,n[e+8],7,1770035416),g,v,n[e+9],12,-1958414417),l,g,n[e+10],17,-42063),m,l,n[e+11],22,-1990404162),v=o(v,m=o(m,l=o(l,g,v,m,n[e+12],7,1804603682),g,v,n[e+13],12,-40341101),l,g,n[e+14],17,-1502002290),m,l,n[e+15],22,1236535329),v=u(v,m=u(m,l=u(l,g,v,m,n[e+1],5,-165796510),g,v,n[e+6],9,-1069501632),l,g,n[e+11],14,643717713),m,l,n[e],20,-373897302),v=u(v,m=u(m,l=u(l,g,v,m,n[e+5],5,-701558691),g,v,n[e+10],9,38016083),l,g,n[e+15],14,-660478335),m,l,n[e+4],20,-405537848),v=u(v,m=u(m,l=u(l,g,v,m,n[e+9],5,568446438),g,v,n[e+14],9,-1019803690),l,g,n[e+3],14,-187363961),m,l,n[e+8],20,1163531501),v=u(v,m=u(m,l=u(l,g,v,m,n[e+13],5,-1444681467),g,v,n[e+2],9,-51403784),l,g,n[e+7],14,1735328473),m,l,n[e+12],20,-1926607734),v=c(v,m=c(m,l=c(l,g,v,m,n[e+5],4,-378558),g,v,n[e+8],11,-2022574463),l,g,n[e+11],16,1839030562),m,l,n[e+14],23,-35309556),v=c(v,m=c(m,l=c(l,g,v,m,n[e+1],4,-1530992060),g,v,n[e+4],11,1272893353),l,g,n[e+7],16,-155497632),m,l,n[e+10],23,-1094730640),v=c(v,m=c(m,l=c(l,g,v,m,n[e+13],4,681279174),g,v,n[e],11,-358537222),l,g,n[e+3],16,-722521979),m,l,n[e+6],23,76029189),v=c(v,m=c(m,l=c(l,g,v,m,n[e+9],4,-640364487),g,v,n[e+12],11,-421815835),l,g,n[e+15],16,530742520),m,l,n[e+2],23,-995338651),v=f(v,m=f(m,l=f(l,g,v,m,n[e],6,-198630844),g,v,n[e+7],10,1126891415),l,g,n[e+14],15,-1416354905),m,l,n[e+5],21,-57434055),v=f(v,m=f(m,l=f(l,g,v,m,n[e+12],6,1700485571),g,v,n[e+3],10,-1894986606),l,g,n[e+10],15,-1051523),m,l,n[e+1],21,-2054922799),v=f(v,m=f(m,l=f(l,g,v,m,n[e+8],6,1873313359),g,v,n[e+15],10,-30611744),l,g,n[e+6],15,-1560198380),m,l,n[e+13],21,1309151649),v=f(v,m=f(m,l=f(l,g,v,m,n[e+4],6,-145523070),g,v,n[e+11],10,-1120210379),l,g,n[e+2],15,718787259),m,l,n[e+9],21,-343485551),l=t(l,i),g=t(g,a),v=t(v,d),m=t(m,h);return[l,g,v,m]}function a(n){var t,r="",e=32*n.length;for(t=0;t<e;t+=8)r+=String.fromCharCode(n[t>>5]>>>t%32&255);return r}function d(n){var t,r=[];for(r[(n.length>>2)-1]=void 0,t=0;t<r.length;t+=1)r[t]=0;var e=8*n.length;for(t=0;t<e;t+=8)r[t>>5]|=(255&n.charCodeAt(t/8))<<t%32;return r}function h(n){return a(i(d(n),8*n.length))}function l(n,t){var r,e,o=d(n),u=[],c=[];for(u[15]=c[15]=void 0,o.length>16&&(o=i(o,8*n.length)),r=0;r<16;r+=1)u[r]=909522486^o[r],c[r]=1549556828^o[r];return e=i(u.concat(d(t)),512+8*t.length),a(i(c.concat(e),640))}function g(n){var t,r,e="";for(r=0;r<n.length;r+=1)t=n.charCodeAt(r),e+="0123456789abcdef".charAt(t>>>4&15)+"0123456789abcdef".charAt(15&t);return e}function v(n){return unescape(encodeURIComponent(n))}function m(n){return h(v(n))}function p(n){return g(m(n))}function s(n,t){return l(v(n),v(t))}function C(n,t){return g(s(n,t))}function A(n,t,r){return t?r?s(t,n):C(t,n):r?m(n):p(n)}"function"==typeof define&&define.amd?define(function(){return A}):"object"==typeof module&&module.exports?module.exports=A:n.md5=A}(this); |
在 hexo/_config.yml
中增加以下内容:
1 | #gitalk settings |
hexo\themes\anatole\layout\partial
目录下打开head.pug
, 在末尾加上以下内容:1 | script. |
本作品系原创,采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,转载请注明出处。