命令执行
通过java.io.IOException
实现命令执行
1 2 3 4 5 6
| import java.io.IOException; public class Main { public static void main(String[] args) throws IOException{ Runtime.getRuntime().exec("calc"); } }
|
通过java.lang.ProcessBuilder
实现命令执行
1 2 3 4 5 6 7 8 9
| import java.lang.ProcessBuilder; import java.io.IOException; public class Main { public static void main(String[] args)throws IOException{ ProcessBuilder processBuilder = new ProcessBuilder(); processBuilder.command("cmd", "/c", "calc"); Process process = processBuilder.start(); } }
|
Java反射
1 2
| Java中存在一个Class类,该类保存了对象和类的所有信息,可通过Class类获取Java中的类信息。 Java的反射就是将某个Java类中的方法或者变量等信息,映射成一个Java对象,通过映射后可获取其中的信息或执行其中的方法。
|
创建Class对象
通过以下几种方式创建Class对象后,可对其执行反射
作用 |
代码 |
获取类名称,并返回Class对象 |
Class.forName(“类名”) |
根据现有对象,创建新的Class对象 |
对象名.getClass() |
根据类名,创建Class对象 |
类名.class |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import java.lang.Class; import java.lang.reflect.*;
class Data { int num = 99; public void print() { System.out.println("成功调用print方法"); } }
public class Main { public static void main(String[] args) throws ClassNotFoundException { Class data1 = Class.forName("Data"); Data data = new Data(); Class data2 = data.getClass(); Class data3 = Data.class; } }
|
反射调用方法(过渡)
通过下面的两个方法获取类中的方法,反射调用
作用 |
代码 |
返回类的方法 |
Class对象名.getMethods(“方法名”,”传参类型”) |
反射调用方法 |
Method方法名.invoke(类的对象,传参) |
如果用下方的代码去命令执行会发现一个问题,已经可以new出相应类的对象了还有必要通过反射再调用方法么
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import java.lang.Class; import java.lang.reflect.*;
class Data { public void print() { System.out.println("成功调用print方法"); } }
public class Main { public static void main(String[] args) throws Exception { Data d = new Data(); Class data = d.getClass(); Method m = data.getMethod("print"); m.invoke(d,null); } }
|
反射调用方法
使用invoke方法反射调用指定方法时,需要传入一个类的对象
在实际的环境中,可能没法通过new来声明一个对象
此时也需要通过反射,先获取该类的构造方法,再通过构造方法创建一个对象
作用 |
代码 |
获取类的构造方法,并返回其对象 |
Class对象名.getConstructor() |
通过构造方法创建类对象 |
Constructor对象名.newInstance() |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import java.lang.Class; import java.lang.reflect.*;
class Data { public Data(){ } public void print() { System.out.println("成功调用print方法"); } }
public class Main { public static void main(String[] args) throws Exception { Class data = Class.forName("Data"); Method m = data.getMethod("print"); Constructor c = data.getConstructor(); Object obj = c.newInstance(); m.invoke(obj); } }
|
Java反射与命令执行
通过java.io.IOException
实现命令执行
如果是通过java.io.IOException
实现命令执行时,需要获取Runtime类构造方法的对象
但它的构造方法被private修饰了,无法直接获取
但Runtime类存在一个public的方法getRuntime可以直接返回Runtime类的对象
所以就不需要通过getConstructor获取构造方法来创建对象,而是通过Runtime的getRuntime方法
1 2 3 4 5 6 7 8 9 10 11 12
| import java.lang.Class; import java.lang.reflect.*;
public class Main { public static void main(String[] args) throws Exception { Class c = Class.forName("java.lang.Runtime"); Method m1 = c.getMethod("getRuntime"); Method m2 = c.getMethod("exec",String.class); Object obj = m1.invoke(null,null); m2.invoke(obj,"calc"); } }
|
通过java.lang.ProcessBuilder
实现命令执行
在ProcessBuilder
类中,其构造方法需要传入一个List类型的数据,用来设置需要执行的命令
获取构造方法时,需要指定类型为List
在创建相应对象时,也需要传入一个List用来设置需要执行的命令信息
作用 |
代码 |
创建List |
Arrays.asList(数据) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import java.lang.Class; import java.lang.reflect.*; import java.util.Arrays; import java.util.List;
public class Main { public static void main(String[] args) throws Exception { Class c = Class.forName("java.lang.ProcessBuilder"); Method m = c.getMethod("start"); Constructor con = c.getConstructor(List.class); Object obj = con.newInstance(Arrays.asList("calc")); m.invoke(obj); } }
|
参考
https://blog.csdn.net/sinat_38259539/article/details/71799078
https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html
https://blog.csdn.net/u013256816/article/details/54603910
https://zhuanlan.zhihu.com/p/343034495
https://www.cainiaojc.com/java/java-reflection.html
https://xz.aliyun.com/t/12446
https://www.cnblogs.com/Nestar/p/17335689.html
https://github.com/wa1ki0g/javasec
https://mp.weixin.qq.com/s/5XL8aOZYtYm8F24TlTTUUQ
https://mp.weixin.qq.com/s/B8iNY5DS7s95WOTCTEK5PA