> For the complete documentation index, see [llms.txt](https://p4d0rn.gitbook.io/java/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://p4d0rn.gitbook.io/java/prerequisites/fan-she/exec.md).

# 反射调用命令执行

### Preface

开发者设计本地命令执行的本意是实现某些程序功能

### Runtime

最简单的命令执行方法

```java
Runtime.getRuntime().exec("bash -c {echo,d2hvYW1p}|{base64,-d}|{bash,-i}");
```

跟踪调用栈可以发现，`Runtime#exec`并不是命令执行的最终点

> java.lang.Runtime#exec
>
> ​ -> java.lang.ProcessBuilder#start
>
> ​ -> java.lang.ProcessImpl#start
>
> ​ -> ProcessImpl#
>
> ​ -> native create

### ProcessBuilder

```java
public final class ProcessBuilder {
    public ProcessBuilder(List<String> command) {
            if (command == null)
                throw new NullPointerException();
            this.command = command;
        }

    public ProcessBuilder(String... command) {
        this.command = new ArrayList<>(command.length);
        for (String arg : command)
            this.command.add(arg);
    }
    public Process start() throws IOException {
        // ...
        try {
            return ProcessImpl.start(cmdarray,
                                     environment,
                                     dir,
                                     redirects,
                                     redirectErrorStream);
        } // ...
    }
}
```

```java
// ProcessBuilder processBuilder = new ProcessBuilder(Arrays.asList("calc"));
ProcessBuilder processBuilder = new ProcessBuilder("calc");
processBuilder.start();
```

### ProcessImpl

非public类，需要使用反射调用

```java
Class clazz = Class.forName("java.lang.ProcessImpl");
Method start = clazz.getDeclaredMethod("start", String[].class, Map.class, String.class, ProcessBuilder.Redirect[].class, boolean.class);
start.setAccessible(true);
start.invoke(clazz, new String[]{"calc"}, null, null, null, false);
```

`ProcessImpl#start`最终调用的是`ProcessImpl`的构造方法

```java
Class clazz = Class.forName("java.lang.ProcessImpl");
Constructor constructor = clazz.getDeclaredConstructor(String[].class, String.class, String.class, long[].class, boolean.class);
constructor.setAccessible(true);
constructor.newInstance(new String[]{"calc"}, null, null, new long[]{-1,-1,-1}, false);
```

最后调用的是`ProcessImpl#create` native方法

![image-20230506140255428](/files/HyvqXvbFTVQuemKe6JsN)

Linux和Mac系统上则是交给`UNIXProcess#forkAndExec` native方法

![image-20230921171548250](/files/iJ3Y1HKpv7ARF2sH4aU9)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://p4d0rn.gitbook.io/java/prerequisites/fan-she/exec.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
