本篇文章给大家带来了关于java的相关知识,其中主要介绍了Java反射机制的相关问题,动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制,希望对大家有帮助。
|
本篇文章给大家带来了关于java的相关知识,其中主要介绍了java反射机制的相关问题,动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制,希望对大家有帮助。
推荐学习:《java教程》 每次听到大佬在讲或者看论坛等一些方式学java反序列化漏洞时,都会有一个词叫做反射机制,大佬顺势借着这个词,就给你造出一个payload,对于刚学java反序列化的我们,可能有点会懵圈,反正我是懵了,所以就赶紧学了一波,不然和大佬差距越来越大。所以这篇文章主要讲述java反射机制 Java反射机制Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。反射被视为动态语言的关键。 我不太擅长文字表达,还是上图操作把 不用反射机制的例子 //定义一个animals接口interface animals {
public abstract void print();}//定义类来实现animals接口的抽象方法class Dog implements animals {
public void print() {
System.out.println("Dog");
}}class Cat implements animals {
public void print() {
System.out.println("Cat");
}}// 构造一个zoo类// 之后如果我们在添加其他的实例的时候只需要修改zoo类class zoo {
public static animals getInstance(String animalsName) {
animals a = null;
if ("Dog".equals(animalsName)) {
a = new Dog();
}
if ("Cat".equals(animalsName)) {
a = new Cat();
}
return a;
}}public class reflection {
public static void main(String[] args) {
//借助zoo类寻找对应的类来实现接口
animals a=zoo.getInstance("Cat");
if(a!=null)
a.print();
}}这时候添加动物,只需要
把上面修改为反射机制 //定义一个animals接口interface animals {
public abstract void print();}//定义类来实现animals接口的抽象方法class Dog implements animals {
public void print() {
System.out.println("Dog");
}}class Cat implements animals {
public void print() {
System.out.println("Cat");
}}// 构造一个zoo类// 之后如果我们在添加其他的实例的时候只需要修改zoo类class zoo {
public static animals getInstance(String className) {
animals a = null;
try {
//借助Class.forName寻找类名,并用newInstance实例化类似于new
a = (animals) Class.forName(className).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return a;
}}public class reflection {
public static void main(String[] args) {
//借助zoo类寻找对应的类来实现接口(classname为当前包名加类名)
animals a = zoo.getInstance("com.cc1.Dog");
if (a != null)
a.print();
}}这时候添加动物只需要
省了一步,传入类名可控,发现好像是存在的类都可以调 反射机制方法我们用的最多的可能是
Class.forName(className).getMethod(methodName).invoke(Class.forName(className).newInstance()); 下面我们用反射机制来弹出计算机(calc)或者记事本(notepad) 由于弹出计算机有点多这次我就弹记事本把,总而言之,能弹出来就很美妙 Runtime.getRuntime().exec("notepad");
类对象获取方式
类初始化 修改zoo类,增加初始块、静态初始块、和构造函数 class zoo {
//初始块
{
System.out.println("1 " + this.getClass());
}
//静态初始块
static {
System.out.println("2 " + zoo.class);
}
public zoo() {
System.out.println("3 " + this.getClass());
}
public static animals getInstance(String className) {
animals a = null;
try {
//借助Class.forName寻找类名,并用newInstance实例化类似于new
a = (animals) Class.forName(className).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return a;
}}类初始化执行顺序:静态初始块 接下来增加zoo1类继承zoo类 class zoo1 extends zoo{
//初始块
{
System.out.println("11 " + this.getClass());
}
//静态初始块
static {
System.out.println("12 " + zoo.class);
}
public zoo1() {
System.out.println("13 " + this.getClass());
}}子类初始化顺序:父类静态初始化块 - > 子类静态初始化块 调用内部类
getMethod
invoke 静态和动态方法的区别
最后我们合并一下 Class.forName("java.lang.Runtime").
getMethod("exec", String.class).
invoke(Class.forName("java.lang.Runtime").getMethod("getRuntime").invoke(Class.forName("java.lang.Runtime")), "notepad");
指定构造方法生成实例String str="notepad";ProcessBuilder pb = new ProcessBuilder(str);pb.start(); getConsturctor(函数可以选定指定接口格式的构造函数(由于构造函数也可以根据参数来进行重载) ProcessBuilder类有两个构造函数
分别使用构造方法
执行完构造方法实例后,在进行强制转化使用start函数即可
实际中,肯定用不了,哪有这么好的事,还是接着反射把 Class.forName(“java.lang.ProcessBuilder”).getMethod(“start”).invoke(clazz.getConstructor(List.class).newInstance(Arrays.asList(“notepad”)));
在这行打断点调试
依旧还是这行打断点
执行私有方法通过函数getDeclaredConstructor获取私有方法,再利用setAccessible(true)打破私有方法限制 Class cls = Class.forName("java.lang.Runtime");
Constructor m = cls.getDeclaredConstructor();
m.setAccessible(true);
cls.getMethod("exec", String.class).invoke(m.newInstance(), "notepad");推荐学习:《java视频教程》 以上就是实例详解Java反序列化之反射机制的详细内容,更多请关注模板之家(www.mb5.com.cn)其它相关文章! |
