This commit is contained in:
2026-02-12 18:09:54 +08:00
commit 50a71d88ba
18 changed files with 869 additions and 0 deletions

39
.gitignore vendored Normal file
View File

@@ -0,0 +1,39 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
.kotlin
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store

10
.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,10 @@
# 默认忽略的文件
/shelf/
/workspace.xml
# 已忽略包含查询文件的默认文件夹
/queries/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# 基于编辑器的 HTTP 客户端请求
/httpRequests/

6
.idea/CoolRequestSetting.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CoolRequestSetting">
<option name="projectCachePath" value="project-91d63062-7c77-470d-abb8-d7928336effe" />
</component>
</project>

7
.idea/encodings.xml generated Normal file
View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
</component>
</project>

14
.idea/misc.xml generated Normal file
View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="zulu-17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

46
pom.xml Normal file
View File

@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.meowrain.aioj</groupId>
<artifactId>codesandboxtest2</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.42</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
<version>5.8.42</version>
</dependency>
<!-- Source: https://mvnrepository.com/artifact/com.github.docker-java/docker-java -->
<dependency>
<groupId>com.github.docker-java</groupId>
<artifactId>docker-java</artifactId>
<version>3.7.0</version>
<scope>compile</scope>
</dependency>
<!-- Source: https://mvnrepository.com/artifact/com.github.docker-java/docker-java-transport-httpclient5 -->
<dependency>
<groupId>com.github.docker-java</groupId>
<artifactId>docker-java-transport-httpclient5</artifactId>
<version>3.7.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,26 @@
/*
* Copyright (c) 2026-2026-2026 MeowRain AI Online Judge
* Author: MeowRain
* Github: https://github.com/meowrain
* Blog: https://blog.meowrain.cn
* Build With Love❤
*/
package cn.meowrain.aioj;
import cn.meowrain.aioj.dto.req.ExecuteCodeRequestDTO;
import cn.meowrain.aioj.dto.resp.ExecuteCodeResponseDTO;
/**
* 代码沙箱接口
*/
public interface CodeSandbox {
/**
* 执行代码
* @param request 执行请求
* @return 执行响应
*/
ExecuteCodeResponseDTO executeCode(ExecuteCodeRequestDTO request);
}

View File

@@ -0,0 +1,132 @@
package cn.meowrain.aioj;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.meowrain.aioj.dto.req.ExecuteCodeRequestDTO;
import cn.meowrain.aioj.dto.resp.ExecuteCodeResponseDTO;
import cn.meowrain.aioj.dto.resp.JudgeInfoDTO;
import cn.meowrain.aioj.utils.ProcessUtil;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
public class JavaDockerCodeSandBox implements CodeSandbox {
private static final long DEFAULT_TIME_LIMIT = 5000L;
public static void main(String[] args) {
JavaDockerCodeSandBox javaDockerCodeSandBox = new JavaDockerCodeSandBox();
String code = ResourceUtil.readStr("testCode.multiargs/Main.java", StandardCharsets.UTF_8);
String language = "java";
ExecuteCodeRequestDTO executeCodeRequestDTO = ExecuteCodeRequestDTO.builder()
.code(code)
.language(language)
.inputList(Arrays.asList("1,2","1,3"))
.build();
ExecuteCodeResponseDTO response = javaDockerCodeSandBox.executeCode(executeCodeRequestDTO);
System.out.println("状态: " + response.getStatus());
System.out.println("消息: " + response.getMessage());
System.out.println("输出: " + response.getOutputList());
if (response.getJudgeInfo() != null) {
System.out.println("判题信息: " + response.getJudgeInfo().getMessage());
System.out.println("耗时: " + response.getJudgeInfo().getTime() + "ms");
System.out.println("内存: " + response.getJudgeInfo().getMemory() + "KB");
}
System.exit(0);
}
@Override
public ExecuteCodeResponseDTO executeCode(ExecuteCodeRequestDTO request) {
String code = request.getCode();
List<String> inputList = request.getInputList();
long timeLimit = request.getTimeLimit() != null ? request.getTimeLimit() : DEFAULT_TIME_LIMIT;
if (inputList == null) {
inputList = Collections.emptyList();
}
ExecuteCodeResponseDTO response = new ExecuteCodeResponseDTO();
// 1. 保存用户代码到临时目录
String userDir = System.getProperty("user.dir");
String globalCodePathName = userDir + File.separator + "tempcode";
if (!FileUtil.exist(globalCodePathName)) {
FileUtil.mkdir(globalCodePathName);
}
String userCodeParentPath = globalCodePathName + File.separator + UUID.randomUUID();
String userCodePath = userCodeParentPath + File.separator + "Main.java";
File userCodeFile = FileUtil.writeString(code, userCodePath, StandardCharsets.UTF_8);
try {
// 2. 编译
String compileError = ProcessUtil.compile(userCodeFile);
if (compileError != null) {
response.setStatus(2);
response.setMessage(compileError);
return response;
}
// 3. 逐个用例执行
List<String> outputList = new ArrayList<>();
long maxTime = 0;
long maxMemory = 0;
for (String input : inputList.isEmpty() ? Collections.singletonList("") : inputList) {
// 构建命令java -cp <classpath> Main <args...>
// inputList 中每个元素按空格拆分为多个命令行参数
List<String> runCommand = new ArrayList<>(Arrays.asList("java", "-Xmx256m", "-cp", userCodeParentPath, "Main"));
if (input != null && !input.trim().isEmpty()) {
runCommand.addAll(Arrays.asList(input.trim().split("\\s+")));
}
ProcessUtil.ExecuteResult result = ProcessUtil.run(runCommand, null, timeLimit);
if (result.isTimeout()) {
response.setStatus(4);
response.setMessage("运行超时");
return response;
}
if (result.getExitCode() != 0) {
response.setStatus(3);
response.setMessage(result.getStderr().isEmpty()
? "运行错误,退出码: " + result.getExitCode()
: result.getStderr());
return response;
}
outputList.add(result.getStdout());
maxTime = Math.max(maxTime, result.getTime());
maxMemory = Math.max(maxMemory, result.getMemory());
}
// 4. 全部执行成功
response.setStatus(1);
response.setMessage("成功");
response.setOutputList(outputList);
JudgeInfoDTO judgeInfo = new JudgeInfoDTO();
judgeInfo.setMessage("Accepted");
judgeInfo.setTime(maxTime);
judgeInfo.setMemory(maxMemory);
response.setJudgeInfo(judgeInfo);
} catch (Exception e) {
response.setStatus(3);
response.setMessage("系统错误: " + e.getMessage());
} finally {
// 5. 清理临时文件
FileUtil.del(userCodeParentPath);
}
return response;
}
}

View File

@@ -0,0 +1,132 @@
package cn.meowrain.aioj;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.meowrain.aioj.dto.req.ExecuteCodeRequestDTO;
import cn.meowrain.aioj.dto.resp.ExecuteCodeResponseDTO;
import cn.meowrain.aioj.dto.resp.JudgeInfoDTO;
import cn.meowrain.aioj.utils.ProcessUtil;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
public class JavaNativeCodeSandbox implements CodeSandbox {
private static final long DEFAULT_TIME_LIMIT = 5000L;
public static void main(String[] args) {
JavaNativeCodeSandbox javaNativeCodeSandbox = new JavaNativeCodeSandbox();
String code = ResourceUtil.readStr("testCode.multiargs/Main.java", StandardCharsets.UTF_8);
String language = "java";
ExecuteCodeRequestDTO executeCodeRequestDTO = ExecuteCodeRequestDTO.builder()
.code(code)
.language(language)
.inputList(Arrays.asList("1,2","1,3"))
.build();
ExecuteCodeResponseDTO response = javaNativeCodeSandbox.executeCode(executeCodeRequestDTO);
System.out.println("状态: " + response.getStatus());
System.out.println("消息: " + response.getMessage());
System.out.println("输出: " + response.getOutputList());
if (response.getJudgeInfo() != null) {
System.out.println("判题信息: " + response.getJudgeInfo().getMessage());
System.out.println("耗时: " + response.getJudgeInfo().getTime() + "ms");
System.out.println("内存: " + response.getJudgeInfo().getMemory() + "KB");
}
System.exit(0);
}
@Override
public ExecuteCodeResponseDTO executeCode(ExecuteCodeRequestDTO request) {
String code = request.getCode();
List<String> inputList = request.getInputList();
long timeLimit = request.getTimeLimit() != null ? request.getTimeLimit() : DEFAULT_TIME_LIMIT;
if (inputList == null) {
inputList = Collections.emptyList();
}
ExecuteCodeResponseDTO response = new ExecuteCodeResponseDTO();
// 1. 保存用户代码到临时目录
String userDir = System.getProperty("user.dir");
String globalCodePathName = userDir + File.separator + "tempcode";
if (!FileUtil.exist(globalCodePathName)) {
FileUtil.mkdir(globalCodePathName);
}
String userCodeParentPath = globalCodePathName + File.separator + UUID.randomUUID();
String userCodePath = userCodeParentPath + File.separator + "Main.java";
File userCodeFile = FileUtil.writeString(code, userCodePath, StandardCharsets.UTF_8);
try {
// 2. 编译
String compileError = ProcessUtil.compile(userCodeFile);
if (compileError != null) {
response.setStatus(2);
response.setMessage(compileError);
return response;
}
// 3. 逐个用例执行
List<String> outputList = new ArrayList<>();
long maxTime = 0;
long maxMemory = 0;
for (String input : inputList.isEmpty() ? Collections.singletonList("") : inputList) {
// 构建命令java -cp <classpath> Main <args...>
// inputList 中每个元素按空格拆分为多个命令行参数
List<String> runCommand = new ArrayList<>(Arrays.asList("java", "-Xmx256m", "-cp", userCodeParentPath, "Main"));
if (input != null && !input.trim().isEmpty()) {
runCommand.addAll(Arrays.asList(input.trim().split("\\s+")));
}
ProcessUtil.ExecuteResult result = ProcessUtil.run(runCommand, null, timeLimit);
if (result.isTimeout()) {
response.setStatus(4);
response.setMessage("运行超时");
return response;
}
if (result.getExitCode() != 0) {
response.setStatus(3);
response.setMessage(result.getStderr().isEmpty()
? "运行错误,退出码: " + result.getExitCode()
: result.getStderr());
return response;
}
outputList.add(result.getStdout());
maxTime = Math.max(maxTime, result.getTime());
maxMemory = Math.max(maxMemory, result.getMemory());
}
// 4. 全部执行成功
response.setStatus(1);
response.setMessage("成功");
response.setOutputList(outputList);
JudgeInfoDTO judgeInfo = new JudgeInfoDTO();
judgeInfo.setMessage("Accepted");
judgeInfo.setTime(maxTime);
judgeInfo.setMemory(maxMemory);
response.setJudgeInfo(judgeInfo);
} catch (Exception e) {
response.setStatus(3);
response.setMessage("系统错误: " + e.getMessage());
} finally {
// 5. 清理临时文件
FileUtil.del(userCodeParentPath);
}
return response;
}
}

View File

@@ -0,0 +1,17 @@
package cn.meowrain.aioj;
//TIP 要<b>运行</b>代码,请按 <shortcut actionId="Run"/> 或
// 点击装订区域中的 <icon src="AllIcons.Actions.Execute"/> 图标。
public class Main {
public static void main(String[] args) {
//TIP 当文本光标位于高亮显示的文本处时按 <shortcut actionId="ShowIntentionActions"/>
// 查看 IntelliJ IDEA 建议如何修正。
System.out.printf("Hello and welcome!");
for (int i = 1; i <= 5; i++) {
//TIP 按 <shortcut actionId="Debug"/> 开始调试代码。我们已经设置了一个 <icon src="AllIcons.Debugger.Db_set_breakpoint"/> 断点
// 但您始终可以通过按 <shortcut actionId="ToggleLineBreakpoint"/> 添加更多断点。
System.out.println("i = " + i);
}
}
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright (c) 2026-2026-2026 MeowRain AI Online Judge
* Author: MeowRain
* Github: https://github.com/meowrain
* Blog: https://blog.meowrain.cn
* Build With Love❤
*/
package cn.meowrain.aioj.dto.req;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 判题请求 DTO
*/
@Data
public class DoJudgeRequestDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 题目提交ID
*/
private Long questionSubmitId;
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright (c) 2026-2026-2026 MeowRain AI Online Judge
* Author: MeowRain
* Github: https://github.com/meowrain
* Blog: https://blog.meowrain.cn
* Build With Love❤
*/
package cn.meowrain.aioj.dto.req;
import lombok.Builder;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
/**
* 代码沙箱执行请求 DTO
*/
@Data
@Builder
public class ExecuteCodeRequestDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 编程语言
*/
private String language;
/**
* 用户代码
*/
private String code;
/**
* 输入用例列表
*/
private List<String> inputList;
/**
* 时间限制ms
*/
private Long timeLimit;
/**
* 内存限制KB
*/
private Long memoryLimit;
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) 2026-2026-2026 MeowRain AI Online Judge
* Author: MeowRain
* Github: https://github.com/meowrain
* Blog: https://blog.meowrain.cn
* Build With Love❤
*/
package cn.meowrain.aioj.dto.resp;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
/**
* 代码沙箱执行响应 DTO
*/
@Data
public class ExecuteCodeResponseDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 输出结果列表(与输入用例一一对应)
*/
private List<String> outputList;
/**
* 执行消息(如编译错误信息、运行错误信息等)
*/
private String message;
/**
* 执行状态1-成功2-编译错误3-运行错误4-超时5-内存超限)
*/
private Integer status;
/**
* 判题信息
*/
private JudgeInfoDTO judgeInfo;
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright (c) 2026-2026-2026 MeowRain AI Online Judge
* Author: MeowRain
* Github: https://github.com/meowrain
* Blog: https://blog.meowrain.cn
* Build With Love❤
*/
package cn.meowrain.aioj.dto.resp;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 判题信息 DTO
*/
@Data
public class JudgeInfoDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 程序执行消息(如 Accepted、Wrong Answer 等)
*/
private String message;
/**
* 消耗内存KB
*/
private Long memory;
/**
* 消耗时间ms
*/
private Long time;
}

View File

@@ -0,0 +1,254 @@
package cn.meowrain.aioj.utils;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* 进程执行工具类,封装编译和运行操作
*/
public class ProcessUtil {
/**
* 执行结果
*/
public static class ExecuteResult {
private final boolean timeout;
private final int exitCode;
private final String stdout;
private final String stderr;
private final long time;
private final long memory;
public ExecuteResult(boolean timeout, int exitCode, String stdout, String stderr, long time, long memory) {
this.timeout = timeout;
this.exitCode = exitCode;
this.stdout = stdout;
this.stderr = stderr;
this.time = time;
this.memory = memory;
}
public boolean isTimeout() {
return timeout;
}
public int getExitCode() {
return exitCode;
}
public String getStdout() {
return stdout;
}
public String getStderr() {
return stderr;
}
public long getTime() {
return time;
}
public long getMemory() {
return memory;
}
}
/**
* 编译 Java 代码
*
* @param userCodeFile 源代码文件
* @param timeoutMs 编译超时时间(毫秒)
* @return 编译成功返回 null失败返回错误信息
*/
public static String compile(File userCodeFile, long timeoutMs) throws IOException, InterruptedException {
ProcessBuilder pb = new ProcessBuilder("javac", "-encoding", "UTF-8", userCodeFile.getAbsolutePath());
pb.redirectErrorStream(true);
Process process = pb.start();
// 异步读取输出流,避免阻塞导致 waitFor 超时失效
StringBuilder outputBuilder = new StringBuilder();
Thread readerThread = new Thread(() -> {
try {
outputBuilder.append(readStream(process.getInputStream()));
} catch (IOException ignored) {
}
});
readerThread.setDaemon(true);
readerThread.start();
boolean finished = process.waitFor(timeoutMs, TimeUnit.MILLISECONDS);
if (!finished) {
process.destroyForcibly();
return "编译超时";
}
readerThread.join(2000);
String output = outputBuilder.toString();
if (process.exitValue() != 0) {
return "编译失败:\n" + output;
}
return null;
}
/**
* 编译 Java 代码,默认 10 秒超时
*/
public static String compile(File userCodeFile) throws IOException, InterruptedException {
return compile(userCodeFile, 10_000L);
}
/**
* 运行程序
*
* @param command 命令及参数列表
* @param input 标准输入内容(可为 null 或空)
* @param timeLimitMs 运行超时时间(毫秒)
* @return 执行结果
*/
public static ExecuteResult run(List<String> command, String input, long timeLimitMs) throws IOException, InterruptedException {
ProcessBuilder pb = new ProcessBuilder(command);
pb.redirectErrorStream(false);
Process process = pb.start();
// 写入标准输入
if (input != null && !input.isEmpty()) {
try (OutputStream os = process.getOutputStream()) {
os.write(input.getBytes(StandardCharsets.UTF_8));
os.flush();
}
} else {
process.getOutputStream().close();
}
// 异步读取 stdout 和 stderr避免管道阻塞
StringBuilder stdoutBuilder = new StringBuilder();
StringBuilder stderrBuilder = new StringBuilder();
Thread stdoutThread = new Thread(() -> {
try {
stdoutBuilder.append(readStream(process.getInputStream()));
} catch (IOException ignored) {
}
});
stdoutThread.setDaemon(true);
Thread stderrThread = new Thread(() -> {
try {
stderrBuilder.append(readStream(process.getErrorStream()));
} catch (IOException ignored) {
}
});
stderrThread.setDaemon(true);
// 内存采样线程:定期采样进程 PID 对应的内存使用KB
long[] maxMemory = {0};
Thread memoryThread = new Thread(() -> {
try {
long pid = process.pid();
while (process.isAlive()) {
long mem = getProcessMemoryKB(pid);
if (mem > maxMemory[0]) {
maxMemory[0] = mem;
}
Thread.sleep(50);
}
} catch (Exception ignored) {
}
});
memoryThread.setDaemon(true);
stdoutThread.start();
stderrThread.start();
memoryThread.start();
long startTime = System.currentTimeMillis();
boolean finished = process.waitFor(timeLimitMs, TimeUnit.MILLISECONDS);
long elapsed = System.currentTimeMillis() - startTime;
if (!finished) {
// 杀死进程
process.destroyForcibly();
return new ExecuteResult(true, -1, "", "", elapsed, maxMemory[0]);
}
stdoutThread.join(2000);
stderrThread.join(2000);
memoryThread.join(1000);
String stdout = stdoutBuilder.toString().trim();
String stderr = stderrBuilder.toString().trim();
return new ExecuteResult(false, process.exitValue(), stdout, stderr, elapsed, maxMemory[0]);
}
/**
* 获取指定 PID 进程的内存使用KB
* Windows 使用 tasklistLinux/Mac 使用 /proc 或 ps
*/
private static long getProcessMemoryKB(long pid) {
Process proc = null;
try {
String os = System.getProperty("os.name").toLowerCase();
ProcessBuilder pb;
if (os.contains("win")) {
pb = new ProcessBuilder("tasklist", "/FI", "PID eq " + pid, "/FO", "CSV", "/NH");
} else {
pb = new ProcessBuilder("ps", "-o", "rss=", "-p", String.valueOf(pid));
}
pb.redirectErrorStream(true);
proc = pb.start();
boolean finished = proc.waitFor(2, TimeUnit.SECONDS);
if (!finished) {
proc.destroyForcibly();
return 0;
}
String output = readStream(proc.getInputStream());
if (os.contains("win")) {
// tasklist CSV 格式: "java.exe","12345","Console","1","123,456 K"
String[] parts = output.split("\"");
for (int i = parts.length - 1; i >= 0; i--) {
String part = parts[i].trim();
if (part.toUpperCase().endsWith("K")) {
String numStr = part.replace("K", "").replace(",", "").replace(" ", "").trim();
return Long.parseLong(numStr);
}
}
} else {
// ps 输出的直接就是 KB 数值
String trimmed = output.trim();
if (!trimmed.isEmpty()) {
return Long.parseLong(trimmed);
}
}
} catch (Exception ignored) {
} finally {
if (proc != null) {
proc.destroyForcibly();
}
}
return 0;
}
/**
* 读取输入流内容为字符串
*/
public static String readStream(InputStream is) throws IOException {
StringBuilder sb = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
String line;
while ((line = reader.readLine()) != null) {
if (sb.length() > 0) {
sb.append(System.lineSeparator());
}
sb.append(line);
}
}
return sb.toString();
}
}

Binary file not shown.

View File

@@ -0,0 +1,15 @@
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<byte[]> holder = new ArrayList<>();
int mb = 1024 * 1024;
long i = 0;
while (true) {
holder.add(new byte[10 * mb]);
i++;
System.out.println("allocated ~" + (i * 10) + "MB");
}
}
}