使用 Java 故意消耗 Cpu 和内存的代码

发布时间 2024-01-04 22:29:20作者: 技术颜良

https://blog.csdn.net/weixin_70730532/article/details/124732635

 

apt install openjdk-8-jdk

 

 

javac ResouceManageService.java

 

 

 

为什么要故意消耗 Cpu 和内存?在项目交付时有时会申请一定的资源进行项目程序代码的部署,一般会预留一些 Cpu 和内存,以便后续扩展项目时能有足够的资源,但有时往往要求很严格,会时不时的检查你的服务器的 cpu 及内存有没有达到一定的使用率要求,如要求 cpu 使用率在 60%以上,内存在 70%以上,如果发现没有达到,为了节省资源,则可能会将配置回收,比如减掉你的 cpu 及内存数量,基于此,使用 Java 程序来空跑业务,来消耗 Cpu 及内存。

1.直接上代码
就一个 Java 类,如下:

import java.util.Vector;


/**
* Cpu部分代码参考https://blog.csdn.net/java2000_net/article/details/3136124
* @author jxlhl
*
*/
public class ResouceManageService {

//是否跑消耗内存代码的标记,默认否,即跑消耗Cpu的代码
private static boolean memConsume = false;

public static void main(String[] args) throws Exception {

final ResouceManageService service = new ResouceManageService();

int num = 1;

for (int i = 0; i < args.length; i++) {

//指定-m表明跑消耗内存,指定-c或不指定为消耗Cpu,
if ("-c".equals(args[i])) {

} else if ("-m".equals(args[i])) {
memConsume = true;
num = Integer.parseInt(args[i + 1]);
i++;
}

}

if(memConsume){

service.memConsume(num);

}else {

service.cpuConsume();

}

}

//只内存消耗调用这个方法
@SuppressWarnings("unchecked")
public void memConsume(int num){

//执行一个for循环进行新生代内存的申请,共消耗num数量GB
for(int i=0;i<num * 10;i++){

@SuppressWarnings("rawtypes")
Vector v = new Vector();
byte b1[] = new byte[104857600]; //100M
v.add(b1);
/*System.out.println(v);
Runtime rt = Runtime.getRuntime();
System.out.println("free memory"+ rt.freeMemory() );*/

}

//内存消耗申请完后,执行死循环休眠,让JVM一直占用申请到的内存,达到一直占用num数量GB的效果
while(true){
try {
Thread.sleep(3600000l);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}

//cpu消耗方法
public void cpuConsume(){
// 角度的分割
final double SPLIT = 0.01;
//
// 2PI分割的次数,也就是2/0.01个,正好是一周
final int COUNT = (int) (2 / SPLIT);
final double PI = Math.PI;
// 时间间隔
final int INTERVAL = 200;
long[] busySpan = new long[COUNT];
long[] idleSpan = new long[COUNT];
int half = INTERVAL / 2;
double radian = 0.0;
for (int i = 0; i < COUNT; i++) {
busySpan[i] = (long) (half + (Math.sin(PI * radian) * half));
idleSpan[i] = INTERVAL - busySpan[i];
radian += SPLIT;
}
long startTime = 0;
int j = 0;
while (true) {
j = j % COUNT;
startTime = System.currentTimeMillis();
while (System.currentTimeMillis() - startTime < busySpan[j])
;
try {

//这里的if控制可以注解掉,让Thread.sleep(idleSpan[j])一直执行。
//我这里加了if控制是因为希望Cpu一直保存在70%以上工作的效果(小于70不sleep),If注解掉将以正弦曲线的趋势使用Cpu
if(idleSpan[j]<70){
Thread.sleep(idleSpan[j]);
}

} catch (InterruptedException e) {
e.printStackTrace();
}

j++;
}
}

}

2.消耗 Cpu 命令
因为是消耗 Cpu,因此在配置 Jvm 时使用了最少的 64M 进行启动,如下

java -XX:InitialHeapSize=64m -XX:MaxHeapSize=64m -XX:NewSize=32m -XX:MaxNewSize=32m -XX:+UseParNewG

3.消耗内存命令
java -XX:InitialHeapSize=4096m -XX:MaxHeapSize=4096m -XX:NewSize=3072m -XX:MaxNewSize=3072m -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:PretenureSizeThreshold=500m -cp "." ResouceManageService -m 1 &

参数说明:-m 表示消耗内存,无此参数表示消耗 Cpu, -m 后面的数字 1 表明消耗 1G 内存

原理: 启动命令时申请最大堆内存 4096Mb,新生代 3072M,程序在启动时将产生 -m 后面数字的内存的数据放在 list 中,然后申请完后,就一直休眠。这样来达到消耗内存不释放的目的。因此-m 后面的数据不能超过新生代配置的内存的最大值,如果需要超过,就把最大内存和新生代的内存配置增加后再启动,如需要一次性消号 6Gb 内存,可用如下示例配置:

java -XX:InitialHeapSize=8192m -XX:MaxHeapSize=8192m -XX:NewSize=7168m -XX:MaxNewSize=7168m -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:PretenureSizeThreshold=500m -cp "." ResouceManageService -m 1 &

XX:PretenureSizeThreshold 设置成了 500MB,是因为我的代码的这一句,byte b1[] = new byte[104857600]; //100M,里面一次申请内存就 100M,为避免申请的对象进入老年代,将 XX:PretenureSizeThreshold 设置调大了

以上命令,可考虑放在shell中保存,以方便执行,如:
####vi start-cpu.sh
#!/bin/sh
java -XX:InitialHeapSize=64m -XX:MaxHeapSize=64m -XX:NewSize=32m -XX:MaxNewSize=32m -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:PretenureSizeThreshold=10m -cp "." ResouceManageService &

####vi start-mem.sh
#!/bin/sh
java -XX:InitialHeapSize=4096m -XX:MaxHeapSize=4096m -XX:NewSize=3072m -XX:MaxNewSize=3072m -X
————————————————
版权声明:本文为CSDN博主「Java烟雨」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_70730532/article/details/124732635