文章字数:251,阅读全文大约需要1分钟
java native interface JNA(Java Native Access)框架是一个开源的Java框架,是SUN公司主导开发的,建立在经典的JNI的基础之上的一个框架
1 |
|
文章字数:251,阅读全文大约需要1分钟
java native interface JNA(Java Native Access)框架是一个开源的Java框架,是SUN公司主导开发的,建立在经典的JNI的基础之上的一个框架
1 |
|
文章字数:251,阅读全文大约需要1分钟
JMH是JDK9自带的JVM基准测试套件,用于定位代码性能,执行时间、吞吐量等
maven依赖引入1 | <dependency> |
maven工程(官方推荐)1 | mvn archetype:generate |
1 | // 预热5次,每次1s |
Mean + Units就是每次操作的毫秒数
1 | Benchmark Mode Samples Mean Mean error Units |
@BenchmarkMode(Mode.Throughput) 和 @OutputTimeUnit(TimeUnit.MILLISECONDS)组合,就是每毫秒吞吐量
943.437 ops/ms
1 | Benchmark Mode Samples Mean Mean error Units |
文章字数:250,阅读全文大约需要1分钟
jni(java native interface)允许java和本地方法交互,但是会丧失平台的可移植性。
java native方法1 | public class HelloWorld { |
javac编译java类1 | javac HelloWorld.java |
javah生成头文件1 | javah HelloWord |
javah生成的头文件声明方法相同的方法。HelloWorldImpl.cpp1 | # include "jni.h" |
1 | static { |
文章字数:1076,阅读全文大约需要4分钟
java内存模型(java Memory Model)是一种符合内存模型规范,屏蔽硬件及操作系统的差异,保证java程序在不同平台下的内存访问效果一致性的机制及规范。
本文整理自-深入理解JVM-内存模型(jmm)和GC的上半部分
随着cpu的发展,内存的读写速度远远赶不上cpu。因此,cpu的厂商在每颗cpu上加上了高速缓存,作为cpu和内存间的缓冲区域。
2.带来的问题
每个cpu各自的一套缓存(一级缓存、二级缓存、三级缓存),如何保证多处理器运算到同一个内存区域时的数据一致性?
为了解决这个问题,各个处理器需要遵循缓存一致性协议与主存交互
在cpu层面,内存屏障(Memory Barrier)提供了支持(硬件层支持):
硬件层的内存屏障分为:
Load Barrier(读屏障)和Store Barrier(写屏障)
1.cpu执行指令可能是;无序的,内存屏障可以组织屏障两侧进行指令重排。
2.强制把写缓冲区/高速缓存中的数据失效,从而强制从主存中获取。
使用关键词volatitle修饰变量
相当于变量读写加锁
1 | public class VolatitleValue { |
1.可见性,该变量的读一定可以看到读之前最后的写
2.原子性,对于该变量的读写具有原子性。
jvm主要有 sun的
HotSpot/JRockit和IBM的IBMJVM,其中HotSpot为主流,在此探讨HotSpot虚拟机。
如开题所说,jmm是jvm的一种规范。使语言不能直接访问硬件内存,作为中转以解决各硬件和操作系统的差异问题。
1 | 方法区、堆是线程共享的 |
线程执行java方法时指向字节码,方便cpu线程切换时切换回正确位置
注:内存中唯一没有OutOfMemoryError的区域
2 虚拟机栈
由栈帧组成,每个方法执行的时候都会创建栈帧存储变量表,操作栈,动态链接,方法出入口等。
注:方法调用入栈,调用完出栈。局部变量表大小在方法运行前就完全确定了
虚拟机栈调用的是java方法(字节码文件),本地方法栈则是调动native方法(c、c++)的实现方法
以下为线程共有的
一般来说对象实例及数组都是在堆上被分配内存。堆作为最大的内存区域也是GC(内存回收机制)主要管理的区域。根据规范,堆可以存在与物理上不连续的内存空间,可设定固定大小也可扩展。(-Xmx和-Xms)。
注:没有内存可分配会报OOM(OutOfMemory)
存储已被虚拟机加载的类信息、常量、静态变量、静态方法、静态代码块。
再回顾一下
线程私有的:
| 区域名 | 作用 |
|---|---|
| 计数器 | cpu线程切换后找到正确位置 |
| jvm栈 | 引用java方法 |
| native栈 | 引用本地c/c++方法及功能 |
线程共享的:
| 区域名 | 作用 |
|---|---|
| 堆 | 对象实例、数组 |
| 方法区 | 类的静态信息 |
1 | 1.对象头// |
对象头(markword)说明:
- 64操作系统下16字节(开启指针压缩12)
- synchronized的锁信息就存储在这里
- 根据锁位偏移有四种锁状态
无锁态、偏向锁、轻量级锁、重量级锁
文章字数:1244,阅读全文大约需要4分钟
1. 减少`minor gc`的频率,将转移到老年代的对象数量降低到最新
2. 减少`full gc`次数
3. 找到并提升性能瓶颈1 | -verbose.gc:显示GC的操作内容。打开它,可以显示最忙和最空闲收集行为发生的时间、收集前后的内存大小、收集需要的时间等。 |
1 | # 新生代和老年代一般内存比例为 1:2 |
Minor GC执行时间不超过50msMinor GC执行频率在10s一次以上Full GC执行时间不到1sFull GC执行频率在10分钟一次以上jps: JVM Process Status Tool, 显示指定系统内所有的HotSpot虚拟机进程。jstat: JVM statistics Monitoring, 是用于监视虚拟机运行时状态信息的命令,它可以显示出虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据。jmap: JVM Memory Map用于生成heap dump文件。jhat: JVM Heap Analysis Tool, 与jmap搭配使用,用来分析jmap生成的dump,jhat内置了一个微型的HTTP/HTML服务器,生成dump的分析结果后,可以在浏览器中查看。jstack: 用于生成java虚拟机当前时刻的线程快照。jinfo: JVM Configuration info实时查看和调整虚拟机运行参数。javap: 查看经javac之后产生的JVM字节码代码,自动解析.class文件, 避免了去理解class文件格式以及手动解析class文件内容。jcmd: 几乎集合了jps、jstat、jinfo、jmap、jstack所有功能,一个多功能工具, 可以用来导出堆, 查看Java进程、导出线程信息、 执行GC、查看性能相关数据等。jconsole: Java Monitoring and Management Console, 监控内存,线程和类jvisualvm: 全能工具,可以分析内存快照、线程快照;监控内存变化、GC变化等MAT: Memory Analyzer Tool, Java heap分析工具,它可以帮助我们查找内存泄漏和减少内存消耗, 基于EclipseGChisto: 分析gc日志的工具HotSpot的JVM里,具有访问权限的java进程的具体状态1 | jps [options] [hostid] |
heap dump文件,如果不使用这个命令,可以使用-XX:+HeapDumpOnOutOfMemoryError参数来让虚拟机出现OOM时自动生成dunp文件文章字数:476,阅读全文大约需要1分钟
SpringBoot中可以使用jpa整合ElasticSearch
jdk 1.8ElasticSearch 2.4需要和springBoot版本匹配com.sun.jna1 | spring-boot-starter-data-elasticsearch |
data-elasticsearch的依赖自带了ES的jar,如果不配置ES实例SpringBoot会自动生成一个。但是性能不如自己搭建的。
1 | spring: |
1 | @Data //lombok |
@Document加在类上| 类型 | 属性名 | 默认值 | 说明 |
|---|---|---|---|
| String | indexName | 无 | 索引库的名称,建议以项目的名称命名 |
| String | type | “” | 类型,建议以实体的名称命名 |
| short | shards | 5 | 默认分区数 |
| short | replica | 1 | 每个分区默认的备份数 |
| String | refreshInterval | “1s” | 刷新间隔 |
| String | indexStoreType | “fs” | 索引文件存储类型 |
@Field属性上加的,相当于@Column,可以不写,默认全部添加到ES中。主键上是@Id。| 类型 | 属性名 | 默认值 | 说明 |
|---|---|---|---|
| FieldType | type | FieldType.Auto | 自动检测属性的类型 |
| FieldIndex | index | FieldIndex.analyzed | 默认情况下分词 |
| boolean | store | false | 默认情况下不存储原文 |
| String | searchAnalyzer | “” | 指定字段搜索时使用的分词器 |
| String | indexAnalyzer | “” | 指定字段建立索引时指定的分词器 |
| String[] | ignoreFields | {} | 如果某个字段需要被忽略 |
1 | @Repository |
文章字数:1807,阅读全文大约需要7分钟
JIT编译等运行数据1 | jstat [ generalOption | outputOptions vmid [ interval[s|ms] [ count ] ] |
-statOption统计参数1 | class #显示有关类加载器行为的统计信息。 |
其它参数
1 | -h n #每n个样本(输出行)显示一个列标题,其中n是一个正整数。 默认值是0,它显示列标题的第一行数据。 |
| 名称 | 简介 |
|---|---|
| S0 | 幸存者0空间利用率占空间当前容量的百分比。 |
| S1 | 幸存者1空间利用率占空间当前容量的百分比。 |
| E | Eden空间利用率占空间当前容量的百分比。 |
| O | 旧空间利用率占空间当前容量的百分比。 |
| M | Metaspace利用率占空间当前容量的百分比。 |
| CCS | 压缩类空间利用率,以百分比表示。 |
| YGC | 年轻一代GC事件的数量。 |
| YGCT | 年轻一代的垃圾收集时间(S)。 |
| FGC | 完整的GC事件的数量。 |
| FGCT | 完整的垃圾收集时间(S)。 |
| GCT | 垃圾收集总时间(S)。 |
| 名称 | 简介 |
|---|---|
| S0C | 当前幸存者空间0容量(kB)。 |
| S1C | 当前幸存者空间1容量(kB)。 |
| S0U | 幸存者空间0利用率(kB)。 |
| S1U | 幸存者空间1利用率(kB)。 |
| TT | 任期阀值 |
| MTT | 最大任期阀值 |
| DSS | 所需的幸存者大小(kB)。 |
| EC | 当前eden空间容量(kB)。 |
| EU | Eden空间利用率(kB)。 |
| YGC | 年轻一代GC事件的数量。 |
| YGCT | 年轻一代的垃圾收集时间(S)。 |
| 名称 | 简介 |
|---|---|
| OGCMN | 最小老年代容量(kB)。#从上图可以看出是670MB |
| OGCMX | 最大老年代容量(kB)。#从上如可以看出最大内存是2730MB |
| OGC | 当前的老年代容量(kB)。 #当前老年代是2730MB |
| OC | 老年代大小(kB)。 |
| YGC | 年轻一代GC事件的数量。 |
| FGC | full GC事件的数量。 |
| FGCT | 完整的垃圾收集时间(S)。 |
| GCT | 垃圾收集总时间(S)。 |
| 名称 | 简介 |
|---|---|
| Loaded | 加载class的数量 |
| Bytes | class字节大小 |
| Unloaded | 卸载的类数。 |
| Bytes | 卸载的千字节数。 |
| Time | 执行类加载和卸载操作的时间。 |
| 名称 | 简介 |
|---|---|
| Compiled | 执行的编译任务数。 |
| Failed | 编译任务的失败数量。 |
| Invalid | 无效的编译任务数。 |
| Time | 执行编译任务的时间。 |
| FailedType | 编译最后一次失败编译的类型。 |
| FailedMethod | 上次失败编译的类名称和方法。 |
| 名称 | 简介 |
|---|---|
| S0C | 当前survivor0区容量(kB)。 #大概是136MB |
| S1C | 当前survivor1区容量(kB)。 #大概是136MB |
| S0U | survivor0区已使用的容量(KB) #当前使用了17MB |
| S1U | survivor1区已使用的容量(KB) |
| EC | Eden区的总容量(KB) #Eden区的大小现在是1092MB |
| EU | 当前Eden区已使用的容量(KB) #当前Eden区使用了1006MB |
| OC | Old空间容量(kB)。 #当前老年代是2730MB |
| OU | Old区已使用的容量(KB) #当前使用了748MB |
| MC | Metaspace空间容量(KB) #在jdk1.7的版本MC是PC,也就是256MB |
| MU | Metacspace使用量(KB) #也就是jdk1.7版本永久代使用了140MB |
| CCSC | 压缩类空间容量(kB)。 |
| CCSU | 压缩类空间使用(kB)。 |
| YGC | 新生代垃圾回收次数 |
| YGCT | 新生代垃圾回收时间 |
| FGC | 老年代 full GC垃圾回收次数 |
| FGCT | 老年代垃圾回收时间 |
| GCT | 垃圾回收总消耗时间 |
| 名称 | 简介 |
|---|---|
| NGCMN | 年轻代(young)中初始化(最小)的大小(KB) |
| NGCMX | 年轻代(young)的最大容量 (KB) |
| NGC | 年轻代(young)中当前的容量 (KB) |
| S0C | 年轻代中第一个survivor(幸存区)的容量 (KB) |
| S1C | 年轻代中第二个survivor(幸存区)的容量 (KB) |
| EC | 年轻代中Eden(伊甸园)的容量 (KB) |
| OGCMN | old代中初始化(最小)的大小 (KB) |
| OGCMX | old代的最大容量(KB) |
| OGC | old代当前新生成的容量 (KB) |
| OC | Old代的容量 (KB) |
| PGCMN | perm代中初始化(最小)的大小 (KB) ,jdk1.8改为了MCMN |
| PGCMX | perm代的最大容量 (KB),jdk1.8改为了MCMX |
| PGC | perm代当前新生成的容量 (KB) |
| PC | Perm(持久代)的容量 (KB) |
| YGC | 从应用程序启动到采样时年轻代中gc次数 |
| FGC | 从应用程序启动到采样时old代(全gc)gc次数 |
| MC | Metaspace空间(KB) |
| CCSMN | 压缩类空间最小容量(kB)。 |
| CCSMX | 压缩类空间最大容量(kB)。 |
| CCSC | 压缩类空间容量(kB)。 |
| 名称 | 简介 |
|---|---|
| NGCMN | 年轻代(young)中初始化(最小)的大小(kb) |
| NGCMX | 年轻代(young)的最大容量 (kb) |
| NGC | 年轻代(young)中当前的容量 (kb) |
| S0CMX | 年轻代中第一个survivor(幸存区)的最大容量 (kb) |
| S0C | 年轻代中第一个survivor(幸存区)的容量 (kb) |
| S1CMX | 年轻代中第二个survivor(幸存区)的最大容量 (kb) |
| S1C | 年轻代中第二个survivor(幸存区)的容量 (kb) |
| ECMX | 年轻代中Eden(伊甸园)的最大容量 (kb) |
| EC | 年轻代中Eden(伊甸园)的容量 (kb) |
| YGC | 从应用程序启动到采样时年轻代中gc次数 |
| FGC | 从应用程序启动到采样时old代(全gc)gc次数 |
| 名称 | 简介 |
|---|---|
| PC | Perm(持久代)的容量 (kb) #jdk1.8是MC Metaspace容量 |
| PU | Perm(持久代)目前已使用空间 (kb) #jdk1.8是MU Metaspace目前的使用量 |
| OC | Old代的容量 (kb) |
| OU | Old代目前已使用空间 (kb) |
| YGC | 从应用程序启动到采样时年轻代中gc次数 |
| FGC | 从应用程序启动到采样时old代(全gc)gc次数 |
| FGCT | 从应用程序启动到采样时old代(full gc)gc所用时间 |
| GCT | 垃圾收集总时间 |
| 名称 | 简介 |
|---|---|
| OGCMN | old代中初始化(最小)的大小 (kb) |
| OGCMX | old代的最大容量(kb) |
| OGC | old代当前的容量 (kb) |
| OC | Old代的容量 (kb) |
| YGC | 从应用程序启动到采样时年轻代中gc次数 |
| FGC | 从应用程序启动到采样时old代(全gc)gc次数 |
| FGCT | 从应用程序启动到采样时old代(full gc)gc所用时间 |
| GCT | 垃圾收集总时间。 |
文章字数:564,阅读全文大约需要2分钟
记一次查找问题的过程
做一个用jpa从数据库中查找数据,修改再保存到数据库的简单功能。
查找出来后使用BeanUtil将修改的信息放入jpa的对象中,结果报了错误Could not copy property 'id' from source to target
查看BeanUtil的源代码
1 | if (readMethod != null && ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) { |
发现在反射调用失败后统一返回这个异常,于是打断点。果然是反射报的异常。
检查属性是否一一对应,是否有公共的get和set,是否有基础类型(有的话传入空会空指针)
都没发现有问题,于是手动赋值又运行了一遍。
1 | a.setId(b.getId()); |
期初只是为了测试一下方法是否被私有化,属性名是否一致。结果抛出异常LazyInitializationException
这才是导致反射出错的原因,异常信息的意思大致是session被关闭。在stackoverflow上找到解决方法:方法上加上@Transactional。
最后成功解决问题,回想了一下。当元素或者元素的lazy属性为true时执行find()得到的只是一个代理对象,只有执行getId()时才会从数据库中取。然后取的时候事务已经关闭了。(可能是因为find操作是在Stream流中进行的,流关闭事务也关闭了)加上@Transactional注解可以使代码块事务统一。
文章字数:569,阅读全文大约需要2分钟
Keytool是一个Java数据证书的管理工具。
Keytool将秘钥(key)和证书(certificates)存在名为keystore的文件中。keystore中有两种数据key entity),私钥+公钥trusted certificate entries),公钥alias别名,不区分大小写。keystore下又若干别名条目-genkey: 在用户主目录中创建一个默认文件.keystore,还会产生一个mykey的别名,mykey中包含用户的公钥、私钥和证书。没有指定目录,会生成在默认目录下。-alias: 产生别名-keystore: 指定秘钥库的名称。加上此命令,生成的各类信息将不在.keystore文件中-keyalg: 指定秘钥的算法,默认DSA,可以设置成RSA-validity: 创建的证书有效期是多少天-keysize: 指定秘钥长度-storepass: 指定秘钥库的访问密码(查看秘钥库内容需要)-keypass: 指定别名条目的密码(私钥的密码)-dname: 指定证书拥有者的信息CN=名字与姓氏,OU=组织单位名称,O=组织名称,L=城市或区域名称,ST=州或省份名称,C=单位的两字母国家代码-list: 显示密钥库中的证书信息,例如keytool -list -v -keystore, -storepass指定密码-v: 显示秘钥库中的证书详细信息-export: 将别名指定的证书导出到文件,-alias指定导出的别名,-keystore指定keystore,-file指定导出证书的位置及证书名称,-storepass密码-file: 指定导出文件的文件名-delete: 删除秘钥库中某条目,keytool -delete -alias指定删除的别名-printcert: 查看导出的证书信息keytool -printcert -file xxx.crt查看导出的证书信息-keypasswd: 修改秘钥库中指定条目口令,-keypasswd -alias指定需要修改的别名,-keypass 旧密码 -new 新密码 -storepass keystore密码 -keystore xxx-storepasswd: 修改keystore口令,-storepasswd -keystore e:\sture.keystore(需修改口令的keystore) -storepass 123456(原始密码) -new 321(新密码)-import: 将签名数字证书导入秘钥库keytool -import -alias指定导入条目的别名 -keystore,-file指定导入的证书生成keystorekeytool -genkey -v -alias broker -keyalg RSA -keystore broker.keystore -storepass brokerPwd -keypass brokerKeyPwd
查看keystorekeytool -list -v -keystore broker.keystore
keystore导出成证书keytool -export -alias broker -keystore broker.keystore -file borker_cert -storepass brokerPwd
导入证书到truststorekeytool -import -v -file borker_cert -keystore client.truststore -storepass clientTrustPwd
jks转p12
keytool -importkeystore -srckeystore keyStore.jks -srcstoretype JKS -deststoretype PKCS12 -destkeystore keyStore.p12
文章字数:546,阅读全文大约需要2分钟
QOS即Quality of Service服务质量,有发布者的QOS和订阅者的QOS
level0: 最多传输一次level1: 至少传输一次level2: 只有一次的传输1 | 生产者---》中间件---》消费者 |
只会发送一次,不管有没有收到。适合不是很重要的数据,比如传感器温度。反正很快会有下一次的数据。
1 | 生产者《------》中间件《-------》消费者 |
接受者需要发送确认信息,确认自己收到了。发送者如果没有收到确认信息就会再次发送。这个保证了发送的信息一定会到达,但是如果确认的信息没有被收到,可能导致重复发送。
1 | 发送者发送信息+信息编号--》接受者接收,保存编号--》确认收到+信息编号 |
增加了信息编号的传递,可以有效防止重复信息,但是多了删除编号的步骤。
并且假如接受者的删除请求没有到达(即没收到删除请求就有新的message)还会多次发送删除请求。
信息发送的次数过多。