


Detailed explanation of the reflection mechanism of Java deserialization with examples
This article brings you relevant knowledge about java, which mainly introduces issues related to the reflection mechanism of java. The function of dynamically obtaining program information and dynamically calling objects is called reflection of the Java language. Mechanism, I hope it will be helpful to everyone.
Recommended study: "java tutorial"
Every time I hear a big guy talking or watch forums and other ways to learn java When deserializing vulnerabilities, there is a word called reflection mechanism. The boss uses this word to create a payload for you. For those of us who have just learned Java deserialization, we may be a little confused. Anyway, I am confused. , so I quickly learned a lesson, otherwise the gap between me and the big guys will become wider and wider. So this article mainly talks about the java reflection mechanism
Java reflection mechanism
Java's reflection (reflection) mechanism means that in the running state of the program, objects of any class can be constructed, and you can understand The class to which any object belongs can understand the member variables and methods of any class, and can call the properties and methods of any object. This function of dynamically obtaining program information and dynamically calling objects is called the reflection mechanism of the Java language. Reflection is seen as the key to dynamic languages.
I’m not very good at expressing myself in words, so let’s use the above picture to illustrate
an example of not using the reflection mechanism
//定义一个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(); }}
To add animals at this time, just
- Add class
- Modify zoo
- Modify the animal class of the main function
Modify the above to the reflection mechanism
//定义一个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(); }}
Add animals at this time Just need to
- Add a class
- Modify the animal class of the main function
It saves a step, the incoming class name is controllable, and it seems to exist Classes can adjust
Reflection mechanism methods
The ones we use most are probably
- forName (calling class)
- getMethod (calling class Method below)
- invoke (execution)
- newInstance (instantiated object)
Class.forName(className).getMethod(methodName).invoke(Class.forName(className).newInstance());
Below we use the reflection mechanism to pop up the computer (calc) or notepad ( notepad)
Since there are a lot of pop-ups on the computer, I will just play Notepad this time. All in all, it’s great to be able to pop it up
Runtime.getRuntime().exec("notepad");
Let’s take a look at the getRuntime function
I learned that this function is the way for the Runtime class to obtain objects. Personally, I feel that it is troublesome to call it every time. In order not to call it once to create an object, it is encapsulated into a function
How to obtain class objects
- Class.forName (obtain class name)
- zoo.class (already loaded class)
- obj .class (instance)
Class initialization
Modify the zoo class, add initial block, static initial block, and constructor
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; }}
Class initialization execution sequence: Static initial block
Class instantiation execution sequence: Static initial block-> Initial block- > Constructor
From this we know that class initialization and class instantiation are different
Next add the zoo1 class to inherit the zoo class
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()); }}
Subclass initialization sequence: Parent class static initialization block - > Subclass static initialization block
Subclass instantiation sequence: Parent class Static initialization block - > Subclass static initialization block - > Parent class initialization block - > Parent class constructor - > Subclass initialization block - > Subclass constructor
It can be known from the above that when Class.forName is used and the class static initialization block is controllable, any code can be executed
Call the internal class
Class.forName("java.lang.Runtime") to get the class (java.lang.Runtime is the full path of the Runtime class)
getMethod
The function of getMethod is to obtain a specific public method of the class through reflection.
Java supports class overloading, but a function cannot be determined by just a function name, so when calling getMethod, a list of parameter types needs to be passed to its method
Class.forName("java.lang.Runtime") .getMethod(“exec”, String.class)
invoke
静态和动态方法的区别
invoke方法在getMethod类下,作用时传递参数,执行方法
public Object invoke(Object obj, Object… args)
第一个参数是getMethod获取的方法的类对象(如果方法是静态方法则传类)
获取exec函数的类对象
Class.forName(“java.lang.Runtime”).getMethod(“getRuntime”).invoke(Class.forName(“java.lang.Runtime”))
由于getRuntime是静态方法,所以传类
invoke(Class.forName(“java.lang.Runtime”).getMethod(“getRuntime”).invoke(Class.forName(“java.lang.Runtime”)),“calc.exe”)
最后我们合并一下
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(函数可以选定指定接口格式的构造函数(由于构造函数也可以根据参数来进行重载)
选定后我们可以通过newInstance(),并传入构造函数的参数执行构造函数
ProcessBuilder类有两个构造函数
- public ProcessBuilder(String… command)(String…变长的字符串数组String[].class)
- public ProcessBuilder(List command)
分别使用构造方法
- Class.forName(“java.lang.ProcessBuilder”).getConstructor(String[].class).newInstance(new String[][]{{“notepad”}})
- Class.forName(“java.lang.ProcessBuilder”).getConstructor(List.class).newInstance(Arrays.asList(“notepad”))
执行完构造方法实例后,在进行强制转化使用start函数即可
( (ProcessBuilder) Class.forName(“java.lang.ProcessBuilder”).getConstructor(List.class).newInstance(Arrays.asList(“notepad”))).start();
实际中,肯定用不了,哪有这么好的事,还是接着反射把
Class.forName(“java.lang.ProcessBuilder”).getMethod(“start”).invoke(clazz.getConstructor(List.class).newInstance(Arrays.asList(“notepad”)));
这里可能有人会好奇我写的里那的另一个构造函数,String…command这个传参为什么用new String[][]{{“notepad”}},不应该是new String[]{“notepad”},现在用应该的
((ProcessBuilder) Class.forName(“java.lang.ProcessBuilder”).getConstructor(String[].class).newInstance(new String[]{“notepad”})).start();
在这行打断点调试
我们传的是一个字符串数组到了实例化的时候变成了一个字符串,再看看另一个构造函数(List)
( (ProcessBuilder) Class.forName(“java.lang.ProcessBuilder”).getConstructor(List.class).newInstance(Arrays.asList(“notepad”))).start();
依旧还是这行打断点
由此可知,List传入时会被当作Object的第一项,而String[]会被当做Object,所以多加一层[]{}
执行私有方法
通过函数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视频教程》
The above is the detailed content of Detailed explanation of the reflection mechanism of Java deserialization with examples. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics



Guide to Perfect Number in Java. Here we discuss the Definition, How to check Perfect number in Java?, examples with code implementation.

Guide to Weka in Java. Here we discuss the Introduction, how to use weka java, the type of platform, and advantages with examples.

Guide to Smith Number in Java. Here we discuss the Definition, How to check smith number in Java? example with code implementation.

In this article, we have kept the most asked Java Spring Interview Questions with their detailed answers. So that you can crack the interview.

Java 8 introduces the Stream API, providing a powerful and expressive way to process data collections. However, a common question when using Stream is: How to break or return from a forEach operation? Traditional loops allow for early interruption or return, but Stream's forEach method does not directly support this method. This article will explain the reasons and explore alternative methods for implementing premature termination in Stream processing systems. Further reading: Java Stream API improvements Understand Stream forEach The forEach method is a terminal operation that performs one operation on each element in the Stream. Its design intention is

Guide to TimeStamp to Date in Java. Here we also discuss the introduction and how to convert timestamp to date in java along with examples.

Capsules are three-dimensional geometric figures, composed of a cylinder and a hemisphere at both ends. The volume of the capsule can be calculated by adding the volume of the cylinder and the volume of the hemisphere at both ends. This tutorial will discuss how to calculate the volume of a given capsule in Java using different methods. Capsule volume formula The formula for capsule volume is as follows: Capsule volume = Cylindrical volume Volume Two hemisphere volume in, r: The radius of the hemisphere. h: The height of the cylinder (excluding the hemisphere). Example 1 enter Radius = 5 units Height = 10 units Output Volume = 1570.8 cubic units explain Calculate volume using formula: Volume = π × r2 × h (4

Spring Boot simplifies the creation of robust, scalable, and production-ready Java applications, revolutionizing Java development. Its "convention over configuration" approach, inherent to the Spring ecosystem, minimizes manual setup, allo
