ホームページ  >  記事  >  Java  >  Java の使い方とサンプルの分析

Java の使い方とサンプルの分析

WBOY
WBOY転載
2023-05-06 16:31:08590ブラウズ

    リフレクション

    リフレクションの定義

    オブジェクトはリフレクションを通じてクラスを取得でき、クラスはすべてのメソッド (Private を含む) を取得できます。 Java 言語のリフレクション機構を通じて、バイトコード ファイルを操作したり、バイトコード ファイルを読み取ったり変更したりすることができます。 #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 をロードするときに使用されます。直接取得

    オブジェクトを取得するには

    .classJava の使い方とサンプルの分析 を使用します##

    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

    特定のメソッドを取得します。最初のパラメータはメソッド名です。2 番目のパラメータは、メソッドのパラメータに対応するクラス オブジェクトです。たとえば、ここでの Runtime の exec メソッド パラメータは文字列なので、2 番目のパラメータは文字列です。ここのパラメータは 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.getMethodsJava の使い方とサンプルの分析

    継承されたクラスのパブリック メソッドを含む、クラスのすべてのパブリック メソッドを返します
    d.getMethod

    パラメータは getDeclaredMethod
    3 と同じです。メンバー変数の取得

    Method
    a のメソッドと同様です。getDeclaredFields

    すべての変数配列を取得しますgetDeclaredField(String name)

    Get specific、パラメータは目的のメソッドの名前です

    c. getFields()
    同様に、public のみを取得できますが、親クラスが含まれます

    d. getField(String name)
    同様に、パラメータは、目的のメソッドの名前です。

    4. コンストラクターを取得します Constructor

    Constructor>[] getConstructors(): パブリック コンストラクターのみを返します

    Constructor< ;?>[] getDeclaredConstructors(): すべてのコンストラクターを返します

    Constructor getConstructor(class>...parameterTypes): パラメーターの型と一致するパブリック コンストラクターと一致します

    Constructor getDeclaredConstructor(class>...parameterTypes ): パラメーターの型と一致するコンストラクターを照合します。

    #後の 2 つのメソッドのパラメーターは、次の 2 つのメソッドの型のクラス オブジェクトです。 Method のパラメーターに似たメソッド パラメーター (例:

    String.class

    5)。リフレクションによってクラス オブジェクトを作成します

    newInstance

    を生成できます。リフレクションを通じてオブジェクトをインスタンス化します。一般に、Class オブジェクトの

    newInstance()# を使用します。 ##クラス オブジェクトを作成するメソッド作成方法は次のとおりです: newInstance メソッドを作成するだけです。 forname メソッドを通じて取得されたクラス オブジェクト

    Class c = Class.forName("com.reflect.MethodTest"); // 创建Class对象
    Object m1 =  c.newInstance(); // 创建类对象

    invoke

    invoke メソッドは java.lang.reflect.Method クラスにあり、特定のオブジェクトのターゲット メソッドを実行するために使用されます。通常、getMethod メソッドと組み合わせて呼び出されます。

    使用法: <pre class="brush:java;">public Object invoke(Object obj, Object... args)</pre>最初のパラメータはクラスのインスタンス、2 番目のパラメータは対応する関数のパラメータです

    obj: 基礎となるメソッドの元となるオブジェクトが呼び出されます。インスタンス化されたオブジェクトである必要があります。

    args: メソッドの呼び出しに使用され、オブジェクトの配列です。パラメータは複数の

    である可能性がありますが、最初のパラメータはメソッドを呼び出すことはできません。修正されていません:

    このメソッドの呼び出しが通常のメソッドの場合、最初のパラメータはクラス オブジェクトです。

    このメソッドの呼び出しが静的メソッドである場合、最初のパラメータはクラスです。

      理解するための例を通して
    • 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("测试成功");
          }
      }

    • これは次のとおりです。簡単に説明すると、

    • Method.invoke (クラスまたはクラス オブジェクト)

    最初に forName がクラスを取得し、次に newInstance がクラス オブジェクトを取得し、次に getMethod がメソッドを取得します。

    Java の使い方とサンプルの分析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");
        }
    }
    しかし、次のことが判明しました。エラーが報告されました

    この問題の理由:

    ##使用されたクラスにはパラメータのないコンストラクターがありません

    使用されるクラス コンストラクターは privateJava の使い方とサンプルの分析

    その場合、解決策は
      setAccessible(true);
    • です。これを使用してアクセス制限を突破します

      Java.lang.reflect.AccessibleObject类是Field,Method和Constructor类对象的基类,可以提供将反射对象标记为使用它抑制摸人Java访问控制检查的功能,同时上述的反射类中的Field,Method和Constructor继承自AccessibleObject。所以我们在这些类方法基础上调用setAccessible()方法,既可对这些私有字段进行操作

      简单来说,私有的属性、方法、构造方法,可以通过这个去突破限制,xxx.setAccessible(true) 可以看到Runtime的构造方法是private的

      Java の使い方とサンプルの分析

      那么这里我们就可以这么去突破限制 先获取构造方法,然后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");
          }
      }

      Java の使い方とサンプルの分析

      这里有一个疑问,如果把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 の使い方とサンプルの分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

    声明:
    この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。