preface
In the past, Java Native Interface (JNI) was used to call C/C++ code to implement some low-level operations. Take CLS clear screen function as an example, you need to write the corresponding C/C++ and generate DLL files, and then call DLL through JNI to achieve the corresponding function, specific steps can refer to this blog: Using JNA to implement CLS (Command line clearing) in Java, this shows how to use the JNI-based JNA framework to invoke DLL files to implement CLS clearing. In Java 17, instead of writing C/C++ code and generating DLLS, you just need to write Java code (which is still in the incubator stage). Here’s how.
implementation
Before we get there, let’s show you the final code:
import jdk.incubator.foreign.CLinker;
import jdk.incubator.foreign.FunctionDescriptor;
import jdk.incubator.foreign.MemoryAddress;
import jdk.incubator.foreign.ResourceScope;
import java.lang.invoke.MethodType;
import static jdk.incubator.foreign.CLinker.C_POINTER;
/** * Clear screen test class **@author butterfly
* @dateThe 2021-11-14 * /
public class Main {
public static void main(String[] args) throws Throwable {
// Run the following command
var tip = "Waiting for screen clearance...";
var begin = 0;
var end = 10;
var interval = 1000;
var backspaces = "\b".repeat(tip.length());
while (begin++ < end) {
tip = tip.substring(1) + tip.charAt(0);
System.out.print(backspaces + tip);
Thread.sleep(interval);
cls();
}
System.out.print("Clear screen successfully");
}
/** * clear the screen */
private static void cls(a) throws Throwable {
// Get the system function
var systemFunction = CLinker.systemLookup().lookup("system").orElseThrow();
// Identifies the return value and parameter type of the system function
var systemHandle = CLinker.getInstance().downcallHandle(
systemFunction,
MethodType.methodType(void.class, MemoryAddress.class),
FunctionDescriptor.ofVoid(C_POINTER)
);
// Get the string "CLS" stored in the local memory segment to execute the system(" CLS ") clean screen function
var clsStr = CLinker.toCString("cls", ResourceScope.newImplicitScope());
// Execute the system(" CLS ") clear functionsystemHandle.invoke(clsStr.address()); }}Copy the code
It can be found that we can call the SYSTEM function in C/C++ directly in Java and execute the CLS clear screen command. The code is not too much.
The effect
Here’s another example of the above code in action:
configuration
Since this function is still in the incubator stage, some configurations are needed to experience it. The following is an example of the configuration of IDEA:
First go to File -> Settings and then go to the following configuration screen:
The Compilation Options configuration is as follows:
--add-modules jdk.incubator.foreign --add-exports java.base/jdk.internal.access=ALL-UNNAMED
Copy the code
Then add the following VM options parameters:
--add-modules jdk.incubator.foreign --enable-native-access ALL-UNNAMED
Copy the code
After completing the above configuration, you can experience the CLS screen clearing function. However, garbled characters will appear when using the RUN window of IDEA, so you need to select the Terminal window or use the CMD command window. Type the following command in the root directory of the project (jni in out\production\jni needs to be replaced with its own project name) :
java --add-modules jdk.incubator.foreign --enable-native-access ALL-UNNAMED -classpath out\production\jni Main
Copy the code
Jna mode
The following is a brief introduction to the implementation of CLS screen clearing function using JNA based on JNI. For details, please refer to the implementation of CLS (Command Line screen clearing) function using JNA in Java. The generation steps of DLL files are not shown here.
The POM configuration is as follows:
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<jna.version>5.10.0</jna.version>
</properties>
<dependencies>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>${jna.version}</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>${jna.version}</version>
</dependency>
</dependencies>
Copy the code
The code structure is as follows:
└ ─ SRC └ ─ the main ├ ─ Java ├ ─ ─ ─ ─ Cls. Java ├ ─ ─ ─ ─ the main. Java │ └ ─ resources ├ ─ ─ ─ ─ clsscreen. DLLCopy the code
Clsscreen. DLL is the file mentioned above.
Cls.java contains the following contents:
import com.sun.jna.Library;
import com.sun.jna.Native;
import java.util.Objects;
/** * CLS clear screen method interface **@author butterfly
* @dateThe 2021-11-20 * /
public interface Cls extends Library {
/** * DLL file name */
String DLL_FILE_NAME = "clsscreen.dll";
/** * read clsscreen. DLL file */
Cls DLL = Native.load(
Objects.requireNonNull(Cls.class.getResource(DLL_FILE_NAME)).getPath().substring(1), Cls.class);
/** * CLS clean screen */
void cls(a);
}
Copy the code
The contents of main.java are as follows:
import java.util.stream.Collectors;
import java.util.stream.Stream;
/** * JNA implements CLS clear screen function test **@author zjw
* @dateThe 2021-11-20 * /
public class Main {
public static void main(String[] args) throws InterruptedException {
// Run the following command
String tip = "Waiting for screen clearance...";
int begin = 0;
int end = 10;
int interval = 1000;
String backspaces = Stream.generate(() -> "\b")
.limit(tip.length())
.collect(Collectors.joining());
while (begin++ < end) {
tip = tip.substring(1) + tip.charAt(0);
System.out.print(backspaces + tip);
Thread.sleep(interval);
Cls.DLL.cls();
}
System.out.print("Clear screen successfully"); }}Copy the code
The effect is as follows: