好久没更新自己的blog 这一个月确实太多事情了 放下了自己ctf的学习进度 话说还是边做笔记变学习有效率

Java程序运行原理

Java程序运行原理其实本质上就是Java虚拟机与跨平台原理

Java程序的运行过程就像“翻译官带着菜谱去不同国家的厨房做饭”,核心是跨平台执行自动管理内存

1.写代码→翻译成通用菜谱 (编译)
·你写的代码:用Java语法写好的java文件,比如一个“西红柿炒蛋”的菜谱(代码)
·编译成字节码:用javac命令把代码翻译成.class文件(字节码)。这相当于把中文菜谱转成“国际通用菜
谱”(字节码),任何国家的厨房(操作系统)都能看懂。

关键点:
·字节码不是机器码,而是一种中间格式,类似“通用菜谱”,需要二次翻译。
·跨平台的关键:每个国家(操作系统)配一个翻译官(JVM)就能用同一份菜谱

2.厨房开工→JVM加载并执行
·启动JVM:运行java命令时,相当于请来翻译官(JVM)进厨房。
·类加载器搬食材:JVM的“搬运工”(类加载器)把菜谱(字节码)和食材(类信息)搬到厨房的不同区域:
。方法区:存放菜谱步骤(类结构、静态变量)。
。堆内存:放炒菜用的锅碗瓢盆(对象实例),比如“西红柿”和“鸡蛋”对象。
。栈内存:记录当前炒菜的步骤(方法调用栈),比如“先热锅再倒油”。
关键点:
·JVM自动管理内存,不用手动清理(垃圾回收)
·每个线程(厨师)有自己的工作台(栈)。

3.边炒菜边优化→解释执行&即时编译(JIT)
·解释执行:翻译官(JVM)逐行读菜谱(字节码),转成机器能执行的指令。比如“切西红柿”翻译成机器码。
·即时编译(JIT):如果某步骤重复多次(比如“翻炒”),JVM会把这部分编译成机器码缓存起来,下次直接执
行,加快速度
关键点:
·解释执行适合启动快,即时编译适合长期运行的高效。
·类似厨师记住常用步骤,不用每次都看菜谱。

4.收尾→垃圾回收
·自动清理:炒完菜后,JVM的“清洁工”(垃圾回收器)会自动扔掉用过的锅(无引用的对象),腾出堆内存

·分代回收:新锅(新生代)和旧锅(老年代)分开清理,提高效率69。

Java反射机制

反射就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法。

通过 Java 的反射机制,程序员可以更深入地控制程序的运行过程。例如,在程序运行时由用户输入一个类名,然后动态获取该类拥有的构造、属性和方法,甚至调用任意类的任意方法。

在Java开发中,我们使用new关键字来创建一个对象,然后在程序运行的时候JVM就会相应的生成这个对象。也就是说我们一旦确定了这个类以及对象,那么就无法进行修改。

那么可不可以在我们程序运行的时候动态的生成一个对象呢?

当然可以。我们把Java程序在运行的时候根据需要动态生成的对象称为Java的反射机制。

在程序运行的时候动态创建一个类的实例
周用实例的方法和访问它的属性

Java代码运行原理:
源码
编译器(javac)纟编译为字节码.class文件
各平台JVM解释器把字节码文件转换成操作系统
指令(跨平台)

了解下什么是反射

Java反射机制是什么?

Java 反射机制是 Java 语言的一个重要特性。在学习 Java 反射机制前,大家应该先了解两个概念,编译期和运行期。

编译期是指把源码交给编译器编译成计算机可以执行的文件的过程。在 Java 中也就是把 Java 代码编成 class 文件的过程。编译期只是做了一些翻译功能,并没有把代码放在内存中运行起来,而只是把代码当成文本进行操作,比如检查错误。

运行期是把编译后的文件交给计算机执行,直到程序运行结束。所谓运行期就把在磁盘中的代码放到内存中执行起来。

Java 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为 Java 语言的反射机制**。简单来说,反射机制指的是程序在运行时能够获取自身的信息。在 Java 中,只要给定类的名字,就可以通过反射机制来获得类的所有信息。

Java 反射机制在服务器程序和中间件程序中得到了广泛运用。在服务器端,往往需要根据客户的请求,动态调用某一个对象的特定方法。此外,在 ORM 中间件的实现中,运用 Java 反射机制可以读取任意一个 JavaBean 的所有属性,或者给这些属性赋值。

img

这里的反射方式

  1. 实例化对象

    • 在反射机制中,我们已经有了一个对象(或者不知道对象类型时),它可以是任何类的实例。
  2. 调用 getClass() 方法

    • 通过调用该对象的 getClass() 方法,我们可以获取该对象的类类型。这种方式不需要在编写代码时提前知道对象的具体类型。
  3. 得到完整的包类名称

    • 使用 getClass() 方法,我们可以获取该对象的完整类名,这包括其所在的包名。这对于动态处理和调试非常有用。

    • - **正常方式**适合静态类型的语言或不需要动态处理的场景,显式类的引入和实例创建。
      - **反射方式**适合需要动态类处理的场景,可以在运行时根据对象的类型做出不同的处理,提供更大的灵活性。
      

      Java 反射机制主要提供了以下功能,这些功能都位于`java.lang.reflect`包。

      - 在运行时判断任意一个对象所属的类。
      - 在运行时构造任意一个类的对象。
      - 在运行时判断任意一个类所具有的成员变量和方法。
      - 在运行时调用任意一个对象的方法。
      - 生成动态代理。

      众所周知,所有 Java 类均继承了 Object 类,在 Object 类中定义了一个 getClass() 方法,该方法返回同一个类型为 Class 的对象。例如,下面的示例代码:

      ```java
      Class labelCls = label1.getClass(); // label1为 JLabel 类的对象

利用 Class 类的对象 labelCls 可以访问 labelCls 对象的描述信息、JLabel 类的信息以及基类 Object 的信息。表 1 列出了通过反射可以访问的信息。

  1. 获取类信息:通过 Class.forName() 方法获取某个类的 Class 对象,然后使用 Class 对象的各种方法获取类的信息,如 getName() 获取类名,getDeclaredMethods() 获取所有方法等。
  2. 创建对象:通过 Class 对象的 getConstructor()getDeclaredConstructor() 方法获取指定构造函数的引用,然后使用 newInstance()newInstance() 方法创建对象。
  3. 访问属性:通过 Class 对象的 getDeclaredField() 方法获取指定属性的引用,然后使用 set()get() 方法设置或获取属性的值。
  4. 调用方法:通过 Class 对象的 getDeclaredMethod() 方法获取指定方法的引用,然后使用 invoke() 方法调用方法并传递参数。
  5. 动态代理:通过 Java 反射实现动态代理,可以在运行时创建一个实现了指定接口的代理类,并实现指定的方法逻辑。

更多的可以去看https://y4er.com/posts/java-deserialization-1/

我觉得写的还行的

什么是反射?反射之中包含了一个「反」字,所以想要解释反射就必须先从「正」开始解释。

我们先来看一段代码

1 fanshe testObj = new fanshe();
2 testObj.setPrice(5);

很简单,就是通过new创建了一个fanshe类的对象testObj,这是[正射]。在这个实例化的过程中,我们需要知道类名,那么实际开发中如果我们不确定类名的话就没办法new一个实例了,为此java搞了一个反射出来。

所以反射就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法


一、通过访问权限区分

反射可通过不同方法获取类成员的访问权限:

  1. 公有成员
    使用 getFields()getMethods(),获取所有公有字段/方法(包括继承的)

    Field[] publicFields = MyClass.class.getFields();
    Method[] publicMethods = MyClass.class.getMethods();
  2. 所有成员(包括私有)
    使用 getDeclaredFields()getDeclaredMethods(),获取本类所有字段/方法(不包含继承的)

    Field[] allFields = MyClass.class.getDeclaredFields();
    Method[] allMethods = MyClass.class.getDeclaredMethods();
  3. 判断具体修饰符
    通过 Modifier 类分析访问权限:

    Field field = MyClass.class.getDeclaredField("privateField");
    boolean isPrivate = Modifier.isPrivate(field.getModifiers());

二、通过继承关系区分

反射可区分成员是否来自父类或接口:

  1. 获取父类信息

    Class<?> superClass = MyClass.class.getSuperclass();
    System.out.println("父类:" + superClass.getName());
  2. 获取接口信息

    Class<?>[] interfaces = MyClass.class.getInterfaces();
    for (Class<?> interfaceClass : interfaces) {
    System.out.println("接口:" + interfaceClass.getName());
    }
  3. 判断是否为继承成员
    通过对比父类与本类成员:

    Method[] parentMethods = superClass.getDeclaredMethods();
    // 遍历本类方法,检查是否在父类中存在同名方法

三、通过成员类型区分

反射可区分字段、方法、构造函数的类型:

  1. 字段类型

    Field field = MyClass.class.getDeclaredField("name");
    Class<?> fieldType = field.getType();
    System.out.println("字段类型:" + fieldType.getName()); // 如 java.lang.String
  2. 方法参数与返回值

    Method method = MyClass.class.getMethod("setName", String.class);
    Class<?> returnType = method.getReturnType(); // void
    Class<?>[] paramTypes = method.getParameterTypes(); // [String.class]
  3. 构造函数参数

    Constructor<?> constructor = MyClass.class.getConstructor(String.class, int.class);
    Class<?>[] constructorParams = constructor.getParameterTypes();

四、通过动态调用区分

反射允许运行时动态操作对象:

  1. 调用公有方法

    Object obj = MyClass.class.newInstance();
    Method publicMethod = MyClass.class.getMethod("publicMethod");
    publicMethod.invoke(obj);
  2. 强制调用私有方法

    Method privateMethod = MyClass.class.getDeclaredMethod("privateMethod");
    privateMethod.setAccessible(true); // 突破私有权限
    privateMethod.invoke(obj);
  3. 修改字段值

    Field privateField = MyClass.class.getDeclaredField("secret");
    privateField.setAccessible(true);
    privateField.set(obj, "newValue");

五、通过元数据特征区分

  1. 判断是否为合成成员
    Java编译器生成的合成成员(如内部类访问外部类的字段):

    Field field = MyClass.class.getDeclaredField("this$0");
    boolean isSynthetic = field.isSynthetic(); // true
  2. 获取注解信息

    Annotation[] annotations = MyClass.class.getAnnotations();
    if (annotations.length > 0) {
    System.out.println("类上存在注解:" + annotations[0].annotationType());
    }

总结

通过反射API可精准区分类成员的以下特性:

维度 反射方法 示例场景
访问权限 getFields() vs getDeclaredFields() 公有/私有字段分离
继承关系 getSuperclass() 判断方法是否来自父类
成员类型 getParameterTypes() 动态适配方法参数
动态操作 Method.invoke() 运行时调用未知方法
元数据特征 isSynthetic() 过滤编译器生成代码