之前陆陆续续学过一点Java安全,笔记一直都没没有系统的写过,现在重新深入学一下之前的知识,会把笔记持续更新过来
反射是java得一个重要特性,它可以获取一个类的所有信息,还可以执行类中的方法
我个人感觉静态语言的安全性是比较高的,因为一个供给使用的静态语言的程序的结构时固定的,能给攻击者能操控影响应用程序的点就十分稀少。而相对应的动态语言的灵活性好,结构也好改变,攻击者的攻击手段也就更多。所以初步感觉Java的安全问题或多或少都受反射影响
静态语言与动态语言
动态语言:是一类在 运行时可以改变自身结构或者变量类型的语言,或者说这一类 语言的结构是在 运行时才被决定的。其中的结构包括但不限于:函数、对象、代码块
代表语言:Javascript C# PHP Python
静态语言:是一类在 运行时不能改变自身结构或者变量类型的语言,也就是说这种 语言的结构在 运行之前就被决定了。
代表语言:C C++
Java作为一种静态语言,之所以拥有动态特性,就是因为有反射机制的存在
Java可以通过反射来不定化一段代码
- public void execute(String className, String methodName) throws Exception {
- Class clazz = Class.forName(className);
- clazz.getMethod(methodName).invoke(clazz.newInstance());
- }
这段代码在没有确定传入的参数是什么的时候,它的功能是未知的。这就是说在编译完成时,它的功能并没完全固定,它的功能会随着不同的情况产生不定的变化。这就是我所理解的反射带给Java的动态特性。
反射是如何赋予Java动态特性的呢?、
先来了解一下Java的类加载机制
一个Java源文件的执行流程主要包括两个过程
使用Javac 将 .java 文件编译成 .class 字节码文件
JVM来运行.class字节码文件
而类加载过程指的就是 JVM 把.class字节码文件里的信息加载到内存中,并生成对象的过程
类加载又分成三个阶段:加载、连接、初始化

了解类加载过程之前,先简单了解一下Java内存模型
Java内存中可以简单了解三个关键分区
线程共享,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据
堆的作用是存放对象实例和数组
每个线程会有一个私有的栈。每个线程中方法的调用又会在本栈中创建一个栈帧。在方法栈中会存放编译期可知的各种基本数据类型(存具体数值)、对象引用(可以理解成指针,存对象在堆里面的具体地址)
它们之间的关系可以简单理解成如下图所示

现在来了解一下类加载的详细过程
java.lang.Class对象在堆中,之后就可以通过这个Class对象来访问方法区的静态数据
init()的过程。这个方法不需要定义,是javac编译器自动收集类中所有类变量的赋值动作和静态代码块中的语句合并来的。若该类具有父类,jvm会保证父类的init先执行,然后再执行子类的init。现在,已经大致了解了Java的类加载过程,继续来看看Java是通过什么东西来实现类加载的。
Java 中类加载是通过类加载器实现的,在Java中类加载器可以分为4种

Class提供了一些函数来获取类的信息
...