您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

Java反射的使用方法及示例分析

2024/11/25 13:21:17发布37次查看
反射反射定义对象可以通过反射获取他的类,类可以通过反射拿到所有⽅法(包括私有) 通过java语言中的反射机制可以操作字节码文件,可以读和修改字节码文件
反射的基本运用1. 获取类对象a. forname()方法只需要知道类名,在加载jdbc的时候会采用 实例代码
public class test1 { public static void main(string[] args) throws classnotfoundexception { class name = class.forname("java.lang.runtime"); system.out.println(name); }}
b. 直接获取使用.class去获取对于的对象
public class test1 { public static void main(string[] args) throws classnotfoundexception { class<?> name = runtime.class; system.out.println(name); }}
c. getclass()方法getclass来获取字节码对象,必须要明确具体的类,然后创建对象
public class test1 { public static void main(string[] args) throws classnotfoundexception { runtime rt = runtime.getruntime(); class<?> name = rt.getclass(); system.out.println(name); }}
d. getsystemclassloader().loadclass()方法这个方法和forname类似,只要有类名就可以了,但是区别在于,forname的静态jvm会装载类,并执行static()中的代码
public class getsystemclassloader { public static void main(string[] args) throws classnotfoundexception { class<?> name = classloader.getsystemclassloader().loadclass("java.lang.runtime"); system.out.println(name); }}
2. 获取类方法a. getdeclaredmethods返回类或接口声明的所有方法,包括public、protected、private和默认方法,但是不包括继承的方法
import java.lang.reflect.method;public class getdeclaredmethods { public static void main(string[] args) throws classnotfoundexception { class<?> name = class.forname("java.lang.runtime"); system.out.println(name); method[] m = name.getdeclaredmethods(); for(method x:m) system.out.println(x); }}
b. getdeclaredmethod获取特定的方法,第一个参数是方法名,第二个参数是该方法的参数对应的class对象,例如这里runtime的exec方法参数为一个string,所以这里的第二个参数是string.class
import java.lang.reflect.method;public class getdeclaredmethod { public static void main(string[] args) throws classnotfoundexception, nosuchmethodexception { class<?> name = class.forname("java.lang.runtime"); method m = name.getdeclaredmethod("exec",string.class); system.out.println(m); }}
c. getmethods返回某个类所有的public方法,包括继承类的public方法
d. getmethod参数同理getdeclaredmethod
3. 获取成员变量同理method的那几个方法
a. getdeclaredfields获取类的成员的所有变量数组,但是不包括父类的
b. getdeclaredfield(string name)获取特定的,参数是想要的方法的名称
c. getfields()同理,只能获得public的,但是包括了父类的
d. getfield(string name)同理,参数是想要的方法的名称
4. 获取构造函数constructorconstructor<?>[] getconstructors() :只返回public构造函数
constructor<?>[] getdeclaredconstructors() :返回所有构造函数
constructor<> getconstructor(类<?>... parametertypes) : 匹配和参数配型相符的public构造函数
constructor<> getdeclaredconstructor(类<?>... parametertypes) : 匹配和参数配型相符的构造函数
后面两个方法的参数是对于方法的参数的类型的class对象,和method的那个类似,例如string.class
5. 反射创建类对象newinstance可以通过反射来生成实例化对象,一般我们使用class对象的newinstance()方法来进行创建类对象
创建的方法就是:只需要通过forname方法获取到的class对象中进行newinstance方法创建即可
class c = class.forname("com.reflect.methodtest"); // 创建class对象object m1 = c.newinstance(); // 创建类对象
invokeinvoke方法位于java.lang.reflect.method类中,用于执行某个的对象的目标方法,一般会和getmethod方法配合进行调用。
使用用法:
public object invoke(object obj, object... args)
第一个参数为类的实例,第二个参数为相应函数中的参数
obj:从中调用底层方法的对象,必须是实例化对象
args: 用于方法的调用,是一个object的数组,参数有可能是多个
但需要注意的是,invoke方法第一个参数并不是固定的:
如果调用这个方法是普通方法,第一个参数就是类对象;
如果调用这个方法是静态方法,第一个参数就是类;
通过一个例子去理解
import java.lang.reflect.invocationtargetexception;import java.lang.reflect.method;public class invoke { public static void main(string[] args) throws classnotfoundexception, instantiationexception, illegalaccessexception, nosuchmethodexception, invocationtargetexception { class c = class.forname("invoke"); object o = c.newinstance(); method m = c.getmethod("test"); m.invoke(o); } public void test(){ system.out.println("测试成功"); }}
简单来说就是这样
方法.invoke(类或类对象)
先forname拿到class,再newinstance获取类对象,再getmethod获取方法,然后调用
runtime的rce例子(访问限制突破)runtime类里面有一个exec方法,可以执行命令
import java.lang.reflect.invocationtargetexception;import java.lang.reflect.method;public class exec { public static void main(string[] args) throws classnotfoundexception, instantiationexception, illegalaccessexception, nosuchmethodexception, invocationtargetexception { class c = class.forname("java.lang.runtime"); object o = c.newinstance(); method m = c.getmethod("exec",string.class); m.invoke(o,"/system/applications/calculator.app/contents/macos/calculator"); }}
但是发现报错了
出现这个问题的原因:
使用的类没有无参构造函数
使用的类构造函数是私有的
那么解决方案就是setaccessible(true);,用这个去突破访问限制
java.lang.reflect.accessibleobject类是field,method和constructor类对象的基类,可以提供将反射对象标记为使用它抑制摸人java访问控制检查的功能,同时上述的反射类中的field,method和constructor继承自accessibleobject。所以我们在这些类方法基础上调用setaccessible()方法,既可对这些私有字段进行操作
简单来说,私有的属性、方法、构造方法,可以通过这个去突破限制,xxx.setaccessible(true) 可以看到runtime的构造方法是private的
那么这里我们就可以这么去突破限制 先获取构造方法,然后setaccessible获取访问权限 然后再最后invoke里面,第一个参数写成con.newinstance()
import java.lang.reflect.constructor;import java.lang.reflect.invocationtargetexception;import java.lang.reflect.method;public class exec { public static void main(string[] args) throws classnotfoundexception, nosuchmethodexception, invocationtargetexception, illegalaccessexception, instantiationexception { class c = class.forname("java.lang.runtime"); constructor con = c.getdeclaredconstructor(); con.setaccessible(true); method m = c.getmethod("exec",string.class); m.invoke(con.newinstance(),"/system/applications/calculator.app/contents/macos/calculator"); }}
这里有一个疑问,如果把con.newinstance单独提取出来,他打开计算器不会显示出来,但是后台的确是启动了,不知道啥原因
import java.lang.reflect.constructor;import java.lang.reflect.invocationtargetexception;import java.lang.reflect.method;public class exec { public static void main(string[] args) throws classnotfoundexception, nosuchmethodexception, invocationtargetexception, illegalaccessexception, instantiationexception { class c = class.forname("java.lang.runtime"); constructor con = c.getdeclaredconstructor(); con.setaccessible(true); object o = con.newinstance(); method m = c.getmethod("exec",string.class); m.invoke(o,"/system/applications/calculator.app/contents/macos/calculator"); }}
后记反射中常用的几个重要方法:
获取类的⽅法: forname
实例化类对象的⽅法: newinstance
获取函数的⽅法: getmethod
执⾏函数的⽅法: invoke
限制突破方法:setaccessible
以上就是java反射的使用方法及示例分析的详细内容。
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product