三湘古邑

我想在那里最蓝的大海扬帆。

0%

JVM致命错误日志(hs_err_pid.log)分析

jvm出现致命错误时,会生成一个错误文件 hs_err_pid<pid>.log,其中包括了导致jvm crash的重要信息,可以通过分析该文件定位到导致crash的根源,从而改善以保证系统稳定。当出现crash时,该文件默认会生成到工作目录下.

背景

并发线程处理PDF文件,jvm出现致命错误时,生成错误文件 hs_err_pid.log。

SIGBUS意味着指针所对应的地址是有效地址,但总线不能正常使用该指针。通常是未对齐的数据访问所致。

查看hs_err_pid.log日志

这里一个重要信息是SIGBUS(0x7)表示jvm crash时正在执行线程试图访问一块无文件内容对应的内存区域,比如超过文件尾的内存区域,或者以前有文件内容对应,现在为另一进程截断过的内存区域。其中SISBUS是信号名称,0x7是信号码,pc=0x00007fa4495592a0指的是程序计数器的值,pid=34372是进程号,tid=0x00007fa320cd2700是线程号。

文件下面是导致crash的线程信息和该线程栈信息,描述信息如下:

1
2
3
Current thread (0x00007fa348028000):  JavaThread "hlooc-task-Orders-9" daemon [_thread_in_vm, id=37394, stack(0x00007fa320bd2000,0x00007fa320cd3000)]

siginfo: si_signo: 7 (SIGBUS), si_code: 2 (BUS_ADRERR), si_addr: 0x00007fa449e29041

以上表示导致出错的线程是0x00007fa348028000(指针),线程类型是JavaThreadJavaThread表示执行的是java线程,关于该线程其它类型还可能是:

  • VMThread:jvm的内部线程
  • CompilerThread:用来调用JITing,实时编译装卸class 。 通常jvm会启动多个线程来处理这部分工作,线程名称后面的数字也会累加,例如:CompilerThread1
  • GCTaskThread:执行gc的线程
  • WatcherThreadjvm周期性任务调度的线程,是一个单例对象。 该线程在JVM内使用得比较频繁,比如:定期的内存监控、JVM运行状况监控,还有我们经常需要去执行一些jstat 这类命令查看gc的情况
  • ConcurrentMarkSweepThreadjvm在进行CMS GC的时候,会创建一个该线程去进行GC,该线程被创建的同时会创建一个SurrogateLockerThread(简称SLT)线程并且启动它,SLT启动之后,处于等待阶段。CMST开始GC时,会发一个消息给SLT让它去获取JavaReference对象的全局锁:Lock

后面的hlooc-task-Orders-9表示线程名,daemon表示该线程为守护线程,再后面的[_thread_in_vm表示线程正在执行虚拟机代码,关于该描述其它类型还可能是:

  • _thread_in_native:线程当前状态
  • _thread_uninitialized:线程还没有创建,它只在内存原因崩溃的时候才出现
  • _thread_new:线程已经被创建,但是还没有启动
  • _thread_in_native:线程正在执行本地代码,一般这种情况很可能是本地代码有问题
  • _thread_in_vm:线程正在执行虚拟机代码
  • _thread_in_Java:线程正在执行解释或者编译后的Java代码
  • _thread_blocked:线程处于阻塞状态
  • …_trans:以_trans结尾,线程正处于要切换到其它状态的中间状态

最后的id=37394表示线程IDstack(0x00007fa320bd2000,0x00007fa320cd3000)表示栈区间。

siginfo: si_signo: 7 (SIGBUS), si_code: 2 (BUS_ADRERR), si_addr: 0x00007fa449e29041这部分是导致虚拟机终止的非预期的信号信息:其中si_signosi_codeLinux下用来鉴别异常的

日志头文件包含概要信息,简述了导致crash的原因。而导致crash的原因很多,常见的原因有jvm自身的bug,应用程序错误,jvm参数配置不当,服务器资源不足,jni调用错误,线程试图访问一块无文件内容对应的内存区域,比如超过文件尾的内存区域,或者以前有文件内容对应,现在为另一进程截断过的内存区域。

查看liunx系统日志messages

crash发生于11:26:33

查看java业务日志busi.log

11:26:33处理了两次同一个PDF文件

结论:线程JavaThread "upp-task-Orders-9"试图访问的PDF文件无文件内容对应的内存区域,并发处理有问题.

源文件

1
2
3
4
5
info_1
info_1
info_1
info_1
info_1

执行
1
:let i=1 | g/1/s//\=i/ | let i=i+1

结果
1
2
3
4
5
info_1
info_2
info_3
info_4
info_5

这是一个针对 ECharts 2.0 版本的Java类库,实现了所有ECharts中的Json结构对应的Java对象,并且可以很方便的创建Option

Read more »

手动清理

查询历史索引

1
curl -XGET -s http://192.168.8.6:9200/_cat/indices | awk '{print $3}'

删除数据

1
2
curl -XDELETE http://192.168.8.6:9200/sw_segment-20220622

删除索引名称为sw_segment-20220622的数据

释放空间

1
curl -XPOST http://192.168.8.6:9200/_forcemerge?only_expunge_deletes=true&max_num_segments=1

常用的linux文件权限:

1
2
3
4
5
6
7
8
444 r--r--r--
600 rw-------
644 rw-r--r--
666 rw-rw-rw-
700 rwx------
744 rwxr--r--
755 rwxr-xr-x
777 rwxrwxrwx

从左至右,1-3位数字代表文件所有者的权限,4-6位数字代表同组用户的权限,7-9数字代表其他用户的权限。
而具体的权限是由数字来表示的,读取的权限等于4,用r表示;写入的权限等于2,用w表示;执行的权限等于1,用x表示;
通过4、2、1的组合,得到以下几种权限:0(没有权限);4(读取权限);5(4+1 | 读取+执行);6(4+2 | 读取+写入);7(4+2+1 | 读取+写入+执行)
以755为例:

1
2
3
1-3位7等于4+2+1,rwx,所有者具有读取、写入、执行权限;
4-6位5等于4+1+0,r-x,同组用户具有读取、执行权限但没有写入权限;
7-9位5,同上,也是r-x,其他用户具有读取、执行权限但没有写入权限。

rwx权限数字解释

chmod也可以用数字来表示权限如 chmod 777 file
语法为:chmod abc file
其中a,b,c各为一个数字,分别表示UserGroup、及Other的权限。

1
2
3
4
r=4,w=2,x=1
若要rwx属性则4+2+1=7;
若要rw-属性则4+2=6;
若要r-x属性则4+1=7。

范例:
1
chmod a=rwx file 


1
chmod 777 file 

效果相同
1
chmod ug=rwx,o=x file 


1
chmod 771 file 

效果相同
若用chmod 4755 filename可使此程序具有root的权限

UIkit 是 YOOtheme 团队开发的一款轻量级、模块化的前端框架,可快速构建强大的web前端界面。UIKit提供了全面的HTML、CSS及JS组件,它们使用简单,容易定制和扩展。
它基于LESS开发,代码结构清晰简单,易于扩展和维护,并且具有体积小、反应灵敏的响应式组件,你可以根据 UIKit 基本的风格样式,轻松地自定义创建出自己喜欢的主题样式。

Read more »

从备份文件还原设定的虚拟机编号到指定存储位置

1
qmrestore vzdump-qemu-101-2021_02_07-xxxx.vma.zst 100 --storage data

windowslinux/macos 对换行的使用不同造成
修改相关的 git 配置

1
2
git config --global core.autocrlf input
git config --global core.safecrlf warn

配置说明
1
2
3
4
git config --global core.autocrlf true # add 时去掉CRLF, checkout 时加回CRLF (应该只在win下配置)
git config --global core.autocrlf input # commit 时去掉CRLF, checkout 时什么都不做 (我的选择)
git config --global core.autocrlf false # 什么都不做 (所有开发人员都在相同平台下)
git config --global core.safecrlf warn # 发现CRLF是警告并继续

二维数组压缩再还原

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package cn.hlooc;

public class ArrayReduceTest {
public static void main(String[] args) {
int[][] arr = new int[11][11];
arr[1][2] = 1;
arr[2][3] = 2;
arr[2][8] = 1;
int sum = 0;
for (int[] int1 : arr) {
for (int int2 : int1) {
System.out.print(int2 + "\t");
if (int2 != 0) {
sum++;
}
}
System.out.println();
}
System.out.println("=========================");
int[][] arr2 = new int[sum + 1][3];

arr2[0][0] = 11;
arr2[0][1] = 11;
arr2[0][2] = sum;

int count = 0;
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
if (arr[i][j] != 0) {
count++;
arr2[count][0] = i;
arr2[count][1] = j;
arr2[count][2] = arr[i][j];
}
}
}
for (int[] int1 : arr2) {
for (int int2 : int1) {
System.out.print(int2 + "\t");
}
System.out.println();
}

int[][] arr3 = new int[arr2[0][0]][arr2[0][1]];
for (int i = 1; i < arr2.length; i++) {
arr3[arr2[i][0]][arr2[i][1]] = arr2[i][2];
}

System.out.println("==================");

for (int[] int1 : arr3) {
for (int int2 : int1) {
System.out.print(int2 + "\t");
}
System.out.println();
}
}
}