IDEA
IEDA卡顿
原因1 :划分的内存空间太小
工具栏 下 help -> Edit custom VM options
如果初始内存和最大内存都设置的太小,可能会出现打不开IDEA的情况;
找到此路径下的vmoptions文件 再次修改保存重启IDEA即可
清空es数据
curl -XPOST 'http://localhost:9200/vops_original_asset_v1/_delete_by_query?conflicts=proceed' -H 'Content-Type: application/json' -d'
{
"query": {
"match_all": {}
}
}'
redis
连接失败问题
- RedisMessageListenerContainer : Connection failure occurred. Restarting subscription task after 5000 ms
– 解决方式 : 检查项目中的和redis.conf中是否都配置了密码
elasticsearch配置问题
跨域无法访问问题
配置network.host 为 0.0.0.0
network.host: 0.0.0.0
elasticsearch-head连接不上
http.cors.enabled: true
http.cors.allow-origin: "*"
linux 命令
压缩
在 Linux 中,有许多种文件压缩格式,如 .tar、.gz、.bz2 和 .zip 等等。使用不同的压缩格式和算法,可以获得不同的压缩比和性能。因此,在使用压缩命令时,需要指定压缩格式和参数,以确保压缩结果符合预期。
下面是常见的压缩命令和参数:
tar 命令:
-c:创建新的压缩文件。
-v:显示压缩进度和文件列表。
-f:指定压缩文件的名称和路径。
-z:使用 gzip 算法进行压缩。
-j:使用 bzip2 算法进行压缩。
例如,要将 /path/to/folder 目录压缩成一个 .tar 文件并使用 gzip 算法压缩,可以使用以下命令:
tar -czvf package.tar.gz /path/to/folder/
要压缩当前目录(即当前所在路径)的所有文件和子目录,您可以使用 tar 命令来完成。下面是一个压缩成 .tar.gz 格式的示例:
tar -czvf archive.tar.gz .
只想压缩成 tar包可以去掉z
tar -cvf archive.tar .
解压缩
在 Linux 中,解压缩安装包的命令通常是 tar 命令。具体的命令参数可能因安装包的格式和压缩算法而异,下面列出一些常见的例子:
解压 .tar 格式的包: tar -xvf package.tar
解压 .gz 格式的包: tar -zxvf package.tar.gz
解压 .bz2 格式的包: tar -jxvf package.tar.bz2
解压 .zip 格式的包: unzip package.zip
内存
查看看内存使用情况 free -h
free -h 是一个 Linux 系统下的命令,用于显示系统内存使用情况。其中 -h 表示以人类可读的方式显示内存大小,即将内存大小转换为易于理解的单位,例如 KB、MB、GB 等。
当在终端中输入 free -h 命令后,会显示系统的内存使用情况,包括:
- total:系统的物理内存总量
- used:已经使用的物理内存大小
- free:未被使用的物理内存大小
- shared:被多个进程共享的物理内存大小
- buffers:用于缓存数据的物理内存大小
- cached:用于缓存文件的物理内存大小
示例输出:
total used free shared buff/cache available
Mem: 7.8G 1.4G 4.9G 128M 1.5G 6.0G
Swap: 0B 0B 0B
其中,Mem 表示系统物理内存的使用情况,Swap 表示系统交换分区的使用情况
拓展 --什么是swap区?
swap 是指 Linux 系统中的交换分区(Swap Partition)。交换分区是一种虚拟内存技术,用于在系统内存不足时,将一部分内存中的数据(通常是不常用的数据)交换到硬盘上,以释放出内存空间,从而避免出现内存不足的情况。
在 Linux 系统中,交换分区通常是指一个硬盘分区,用于存储被交换出的内存数据。当系统需要更多的内存时,就会将一部分内存数据(包括未使用的内存和不常用的内存数据)交换到交换分区中,从而释放出更多的内存供系统使用。
防火墙
VOPS 防火墙列表路径
/etc/sysconfig
vim iptables
4.1 查看防火墙状态命令
1) systemctl status firewalld
2) firewall-cmd --state
4.2 关闭防火墙命令
1)临时性关闭(重启后失效): systemctl stop firewalld
2) 永久性关闭(重启后生效): systemctl disable firewalld
4.3 开启防火墙命令
1)临时性开启(重启后失效): systemctl start firewalld
2) 永久性开启(重启后生效): systemctl enable firewalld
第二种:
service iptables status
service iptables stop
service iptables start
永久性生效,重启后不会复原 : chkconfig iptables off
Mysql
日志文件导致磁盘空间过大
-- 查看 日志文件
show binary logs
-- 删除日志文件
purge binary logs to 'LAPTOP-EMOMQ354-bin.000068';
purge binary logs to 'LAPTOP-EMOMQ354-bin.000069';
purge binary logs to 'LAPTOP-EMOMQ354-bin.000070';
purge binary logs to 'LAPTOP-EMOMQ354-bin.000064';
purge binary logs to 'LAPTOP-EMOMQ354-bin.000065';
purge binary logs to 'LAPTOP-EMOMQ354-bin.000066';
purge binary logs to 'LAPTOP-EMOMQ354-bin.000067';
登录数据库
mysql -u root -h 127.0.0.1 -p
启动数据库
systemctl start mysqld.service
systemctl stop mysqld.service
systemctl restart mysqld.service
查看版本
status;
查看密码复杂度
show variables like ‘validate_password%’
修改密码
mysql> select user,host from user;
alter user ‘root’@‘localhost’ identified by ‘1234567’;
alter user ‘root’@‘%’ identified by ‘Gold9encis#’;
mysqladmin -u root -p password “goldencis”
修改密码复杂策略
set global validate_password.length=8;
set global validate_password.special_char_count=0;
set validate_password.policy = Low;
关于 mysql 密码策略相关参数; 1)、validate_password_length 固定密码的总长度;
2)、validate_password_dictionary_file 指定密码验证的文件路径;
3)、validate_password_mixed_case_count 整个密码中至少要包含大/小写字母的总个数;
4)、validate_password_number_count 整个密码中至少要包含阿拉伯数字的个数;
5)、validate_password_policy 指定密码的强度验证等级,默认为 MEDIUM; 关于
validate_password_policy 的取值: 0/LOW:只验证长度; 1/MEDIUM:验证长度、数字、大小写、特殊字符;
2/STRONG:验证长度、数字、大小写、特殊字符、字典文件;
6)、validate_password_special_char_count 整个密码中至少要包含特殊字符的个数;
配置失败处理策略
1.查看失败处理策略
show variables like '%connection_control%';
若返回
则 安装插件 命令如下:
install plugin connection_control soname "connection_control.so";
若返回
表示已安装过失败处理插件
2.修改配置文件
查看my.cnf所在位置
whereis my.cnf
进入所在位置,在mysqld所在区域追加如下配置
connection-control-failed-connections-threshold=3 #锁定此处
connection-control-min-connection-delay=10000 #锁定时间 10s
3.最后查看是否配置成功
show variables like '%connection_control%';
配置口令更换策略
# 使 expuser 账号密码立即过期
mysql> ALTER USER 'expuser'@'%' PASSWORD EXPIRE;
# 修改账号密码永不过期
mysql> ALTER USER 'expuser'@'%' PASSWORD EXPIRE NEVER;
#修改账号密码1天后过期
mysql> ALTER USER 'root'@'%' PASSWORD EXPIRE INTERVAL 1 DAY;
密码过期后会出现以下问题
You must reset your password using ALTER USER statement before executing this statement.
解决方法如下:
#密码重设
alter user 'root'@'%' identified by 'Gold9encis#';
#刷新
flush privileges;
开启日志审计
开启general_log
set global general_log=on
#检查验证
show variables like '%general_log%';
弊端:只要用户执行了操作,无论对错,MySQL就会记录日志,这样的话日志量会非常庞大,对数据库效率有影响
开启 SSL
set global require_secure_transport=ON;
maven
由于网络问题造成的批量包下载失败问题
清除下载失败的jar包
set REPOSITORY_PATH=你的maven仓库全路径
rem 正在搜索...
for /f "delims=" %%i in ('dir /b /s "%REPOSITORY_PATH%\*lastUpdated*"') do (
del /s /q %%i
)
rem 搜索完毕
pause
将此段脚本写入bat文件中(mavenclean.bat),双击执行
内存模型
每个线程都只能访问自己的线程栈。
每个线程都不能访问(看不见)其他线程的局部变量。所有原生类型的局部变量都存储到线程栈中,因此对其他线程是不可见的
线程可以将一个原生变量值的副本传给另一个线程,但不能共享原生局部变量本身。
堆内存中包含了java代码中创建的所有对象,不管是哪个线程创建的。其中也涵盖了包装类型。
不管是创建一个对象并将其赋值给局部变量,还是赋值给另一个对象的成员变量,创建的对象都会被保存到堆内存中。
原生数据类型:
编程语言中的基本数据类型,也称为基本类型或内置类型。这些数据类型通常由语言本身提供,而不是由程序员定义。原生数据类型包括整数(如int、long、short)、浮点数(如float、double)、字符(如char)、布尔值(如bool)等
- 如果是原生数据类型的局部变量,那么它的内容就全部类型保留在线程栈中
- 如果是对象引用,则栈中的局部变量的槽位中保存着对象的引用地址,而实际的对象内容保存在堆中。
- 对象的成员变量与对象本身一起存储在堆上,不管成员变量的类型是原生数值还是对象引用。
- 类的静态变量则和类定义一样都保存在堆中
总结 : 方法中的原生类型和对象引用地址在栈上存储;其他(对象、类定义、静态变量)在堆上
另外 ,堆内存又称为"共享堆",堆中的所有对象可以被所有线程访问,只要能拿到该对象的引用地址
如果两个线程同时访问某个对象的一个方法,则他们都可以访问到这个对象的成员变量,但每个线程的局部变量副本式独立的,因此这也就导致了并发相关的问题
public class Example {
private int count = 0;
public void increment() {
int localCount = count;
localCount++;
count = localCount;
System.out.println("Thread " + Thread.currentThread().getId() + " : Count is " + count);
}
}
public static void main(String[] args) {
Example ex = new Example();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
ex.increment();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
ex.increment();
}
});
t1.start();
t2.start();
}
结果
Thread 11 : Count is 2
Thread 11 : Count is 3
Thread 11 : Count is 4
Thread 11 : Count is 5
Thread 11 : Count is 6
Thread 12 : Count is 2
Thread 12 : Count is 7
Thread 12 : Count is 8
Thread 12 : Count is 9
Thread 12 : Count is 10
JVM内存整体结构
栈结构
每启动一个线程,JVM就会在栈空间栈分配对应的线程栈,如果使用了JNI方法,就会分配一个单独的本地方法栈(Navicat Statck)。某个线程在执行的过程中,一般会包含多个方法,比如A调用B、B调用C、C调用…每执行到一个方法,就会创建对应的栈帧。
程序计数器
- 字节码通过读取程序计数器的值依次读取指令,从而完成顺序执行,循环,选择,异常处理等;
- 另外在多线程的情况下,记录当前线程运行的位置;
堆结构
对是所有线程共用的内存空间 ,JVM将Heap 内存空间氛围年轻代和老年代两部分。
- 年轻代 :新生区 存活区(s0 和 s1 ,s0和s1其中一个为0)
- 老年代 :老年区(确定为长期存活的对象)
非堆
非堆不归GC管理,也分为三个区
元数据区、class space、 codeCache
元数据区 元空间使用的是直接内存 主要说的是方法区 存储类定义信息 运行时常量等;方法区中又包含常量池
public class MyClass {
public static final String MESSAGE = "Hello, world!";
public static final int NUMBER = 42;
}
1.8之后,将字符串常量池移动到了堆中,因为在堆中可以进行GC处理。
String s1 = "Hello";
String s2 = "Hello";
String s3 = new String("Hello");
System.out.println(s1 == s2); // true
System.out.println(s1 == s3); // false
System.out.println(s1.equals(s3)); // true
堆外内存
是指不在 Java 堆中分配的内存空间。在 Java 中,所有的对象都是在堆中分配的,堆外内存则是指除了堆以外的内存空间,如直接内存(Direct Memory)。不归GC管理
哪些对象会在堆外内存?
1.NIO Buffer:Java 中的 NIO(New I/O)库提供了一种基于缓冲区(Buffer)的 I/O 操作方式,NIO Buffer 可以使用直接内存,以提高 I/O 操作的性能。下吗如下:
import java.nio.ByteBuffer;
public class DirectBufferExample {
public static void main(String[] args) {
// 分配直接内存
ByteBuffer directBuffer = ByteBuffer.allocateDirect(1024);
// 操作直接内存
directBuffer.putInt(123);
// 释放直接内存
directBuffer.clear();
}
}
2.JNI 对象:Java Native Interface(JNI)允许 Java 代码调用本地代码,本地代码也可以调用 Java 代码。JNI 对象是在本地代码中分配的,因此它们通常分配在直接内存中。一般使用native 修饰
public class JNIExample {
static {
System.loadLibrary("JNIExample");
}
// 声明本地方法
private native int add(int a, int b);
public static void main(String[] args) {
// 创建 JNIExample 对象
JNIExample example = new JNIExample();
// 调用本地方法
int result = example.add(1, 2);
// 输出结果
System.out.println("Result: " + result);
}
}
3.大对象:Java 中的大对象(Large Object)通常指内存占用比较大的对象,如大数组、大字符串等。由于这些对象占用的内存较大,如果将它们分配到 Java 堆中,可能会导致堆空间的不足。因此,这些大对象通常会分配到直接内存中。
常见错误
java.lang.OutOfMemoryError
- GC Overhead Limit Exceeded : 当 JVM 花太多时间执行垃圾回收并且只能回收很少的堆空间时,就会发生此错误
- Java heap space:假如在创建新的对象时, 堆内存中的空间不足以存放新创建的对象, 就会引发此错误。(和配置的最大堆内存有关,且受制于物理内存大小。最大堆内存可通过-Xmx参数配置,若没有特别配置,将会使用默认值
java.lang.StackOverflowError
- 若栈的内存大小不允许动态扩展,那么当线程请求栈的深度超过当前 Java 虚拟机栈的最大深度的时候
JVM 启动参数
1. 系统属性参数
配置运行的环境变量 这些配置只影响当前的jar的运行情况
可以配置哪些参数?
操作系统环境变量中的任何任何一个
可以通过什么方式配置?
1.直接在系统环境变量中配置
2.在启动脚本中配置 如下
3.在代码中配置 如下
如何获取配置好的参数?
2. 运行模式参数
一般使用 -service 方式启动 内存管理的效率高
3. 堆内存设置参数
- -Xmx: 指定最大堆内存 只与堆内有关系 与非堆和栈无关系
- -Xms: 指定初始内堆内存 ,当指定的初始内存不够时,开始扩容直至Xmx; 一定要保持-Xms和-Xmx一致,否则可能回到值内存抖动
- -Xmn: 等价于 -XX:NewSize,表示的是年轻代整体大小
使用G1垃圾回收是否还要用设置此值?
- -XX: MaxPermSize=size :这是 JDK1.7 之前使用的。Java8 默认允许的Meta空间无限大,此参数无效。
- -XX: MaxMetaspaceSize=size: Java8 默认不限制 Meta 空间,一般不允许设置该选项
- -XX: MaxDirectMemorySize=size, 设置堆外内存 这个参数和 -Dsun.nio.MaxDireMemorySize效果相同
- -Xss:设置每个线程栈的字节数,影响栈的深度。例如 -Xss1m 指定线程栈为1MB,与 -XX:ThreadstatckSize=1m 等价
4. GC 设置参数
- -XX: +UseG1GC: 使用 G1 垃圾回收器
- -XX: +UseConcMarkSweepGC: 使用 CMS 垃圾回收器
- -XX: +UseSerialGC: 使用串行垃圾回收器
- -XX: +UseParallelGC: 使用并行垃圾回收器
5. 分析诊断参数
-XX: ±HeapDumpOnOutOfMemoryError 选项,当 OutOfMemoryError 产生,即内存溢出(堆内存或持久代)时,自动 Dump 堆内存。 与 HeapDumpOnOutOfMemoryError 搭配使用,指定内存溢出时 Dump 文件的目录。
示例用法:
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/heapdump.hprof
发生致命错误时 (fatal error) 执行的脚本例如,写一个脚本来记录出错时间,执行一些命令,或者 curl 一下某个在线报警的 url。示例用法: java -XX:OnError="gdb - %p"MyApp可以发现有一个 %p 的格式化字符串,表示进程 PID.XX: OnOutOfMemorvError 选项,抛出 OutOfMemorvError 错误时执行的脚本XX: ErrorFile=filename 选项,致命错误的日志文件名,绝对路径或者相对路径
-Xdebug -Xrunidwp:transport=dt socket,server=y,suspend=n,address=1506,远程调试
6. JavaAgent 参数
无
JDK内置命令行工具
jstat
jmap
- jmap -heap pid
打印堆内存的配置和使用信息 - jmap -histo pid
打印类占用空间 - jmap -dump:format=b,file=xx.hprof pid
- 生成快照
jstack
GC策略
标记清除法
先标记不可达对象 - >清除不可达对象 (导致内存碎片化)
标记复制法
标记存活对象->将存活对象复制到s1或者s0,清除eden区和其中一个存货区
标记清除整理算法
先标记不可达对象 - >清除不可达对象 (导致内存碎片化)-> 碎片整理 压缩
在进行标记的时候 程序停下来 标记并且清除完之后 程序再继续跑。对此是让全部停下来还是一部分停下来 有个不同的实现,也就有了不同的GC算法。
GC算法
串行GC
-XX:+UseSerialGC
对年轻代使用标记复制法 对老年代使用标记清除整理法
两者都是单线程,当进行GC 时,停止所有线程 ,只让一个CPU 进行垃圾回收,不能利用多核CPU
并行GC
-XX:+UseParallelGC
-XXParallelGCThreads= N 指定GC的核心线程数 不设置便是默认CPU核数
对年轻代使用标记复制法 对老年代使用标记清除整理法
在垃圾回收时,充分利用多CPU,同时进行垃圾回收
CMS GC
XX:+UseConcMarkSweepGC
其对年轻代采用并行 STW 方式的 mark-copy(标记-复制)算法,对老年代主要使用并发 mark-sweep(标记-清除)算法。
四种引用
强引用
new 一个对象便是强引用对象,如果一个对象具有强引用,在可达范围内,即使内存空间不够,即使报内存溢出错误 也不会回收该对象,
软引用
SoftReference<String> ref = new SoftReference<>(str);
str = null; // 释放强引用
String value = ref.get(); // 获取软引用对象
System.out.println(value); // 输出“hello”
当内存不足时,软引用对象会被回收,软引用同样也必须和引用队列一起使用。当垃圾回收器准备回收一个对象时,如果发现这个对象只存在软引用,而且内存不足,那么就会将这个软引用加入到引用队列中。开发人员可以通过检查引用队列中的软引用,来判断对象是否已经被回收。
弱引用
作用:用来解决内存泄漏的问题,比如ThreadLcoal
如果一个对象没有直接引用,仅存在弱引用,GC看到则会被回收掉
ThreadLocal
解决什么样的问题?
线程之间数据隔离,避免线程安全问题,帮助每个线程存储此ThreadLocal所代表的值
原理
ThreadLocal起作用最主要的东西依赖三方面的配置——Threadlocal,ThreadLcoalMap,Thread
每个Thread里有一个 ThreadLcoalMap,当为这个线程存储ThreadLocal所指定的对象时,先看看此Thread有没有ThreadLcoalMap,没有就创建;然后threadLocal 调用 set()方法,此threadLocal作为key,指向的对象作为value存入ThreadLcoalMap中;
ThreadLocal 内存泄露问题是怎么导致的?
ThreadLocalMap 中使用的 key 为 ThreadLocal 的弱引用,而 value 是强引用。所以,如果 ThreadLocal 没有被外部强引用的情况下,在垃圾回收的时候,key 会被清理掉,而 value 不会被清理掉。这样一来,ThreadLocalMap 中就会出现 key 为 null 的 Entry。假如我们不做任何措施的话,value 永远无法被 GC 回收,这个时候就可能会产生内存泄露。ThreadLocalMap 实现中已经考虑了这种情况,在调用 set()、get()、remove() 方法的时候,会清理掉 key 为 null 的记录。使用完 ThreadLocal方法后 最好手动调用remove()方法
数据丢失问题
首先,ThreadLocalMap中所软引用的对象为本身的ThreadLcoal对象,另外软引用对象只有在没有直接引用的情况下才能被GC回收;
举个例子:
public static void main(String[] args) {
WeakReference weakReference = new WeakReference<>(new M());
System.out.println(weakReference.get());
System.gc();
System.out.println(weakReference.get());
}
输出结果:
threadlocal.M@1540e19d
null
第一次可以获取这个对象,在执行GC之后,此对象变获取不到了
换一种方式
public static void main(String[] args) {
M m = new M();
WeakReference weakReference = new WeakReference<>(m);
System.out.println(weakReference.get());
System.gc();
System.out.println(weakReference.get());
}
输出结果:
threadlocal.M@1540e19d
threadlocal.M@1540e19d
第一次可以获取到对象,GC之后仍然能获取到对象,为什么?
根本原因是:弱引用的对象会在“没有直接引用之后被GC掉”不是"会被GC掉”(这种是软引用),ThreadLocal用弱引用是为了防止用完了不调用remove造成的内存泄漏,对正常使用没有影响,另外,用完之后还要手动的去清空此对象,因为GC只是回收的ThrealLcoalMap中ThrealLcoal这个key,而Map中的value没有回收
CAS
compare and swap
读取当前值E,进行运算得到A,先不更新,再次读取E,比较此时的E是否与上次读取的E相等,如果相等,将E更新为A
如果读取到E与上次不相等,再重复上面的步骤,读取,进行运算,比较,更新;
ABA 问题
什么是ABA问题
一个线程将A改为B,后B经过本线程或者其他线程又变成A,此时的A与上次的A不一样,这就是ABA问题
如何解决?
加版本号
比较时,不管比较值,还比较版本号
锁升级过程
前后端传参接收为null的问题
- @RequestBody:用来接收前端传递给后端的json字符串中的数据(数据在请求体中)
前端 必须是 Content-Type:application/json
另外 raw 对应的是 Content-Type: text/plain
弄错后容易导致 后端接收到的参数为空