java35-克隆-浅克隆-深克隆-java参数值传递-RMI-代理模式-静态代理-动态代理JDK-invocationHandler-newProxyInstance

时间
4/25

克隆

概述

克隆出现的原因:
在实际开发过程中,一个对象obj已经包含一些有用信息,这是我们需要将obj的信息复制到obj2中,使得obj和obj2对象具有两个完全不同的地址,修改一个对象的值,另一个对象不受影响。

实现克隆的方式
实现Cloneable接口,并重写object类中的clone方法,可以实现浅克隆,也可以实现深克隆
1 被克隆对象所属类必须实现Cloneable接口
	public class 类名 implements Cloneable{
		private 属性类 属性名;
		}
1-1 要想实现深克隆的话,类的成员属性 所在的类也需要实现Cloneable接口
	public class 属性类 implements Cloneable{}
2 所属类必须重写Object类的clone方法
	@Override
	public Object clone() throws CloneNotSupportedException{
		类名 obj =(类名)super.clone(); // 浅克隆
		obj.属性名 = (属性类)属性名.clone(); //深克隆
		return obj;
}
实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的克隆
// 要序列化对象所属类 需要实现Serializable接口
public class 类名 implements Serializable{}
// 序列化
1 创建序列化流
	ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("文件路径"));
2 创建对象
	类名 obj = new 类名();
3 使用序列化流的writeObject方法将对象写入指定的ObjectOutputStream流中
	oos.writeObject(obj);
4 释放资源
	oos.close();
	
// 反序列化
1 创建反序列化流
	ObjectInputStream ois = new ObjectInputStream(new FileInputStream("文件路径"));
2 使用反序列化流的readObject方法从ObjectInputStream流中读取一个对象
	Object obj = ois.readObject();
3 强制转化对象类型
	类型 obj1 = (类型)obj;
4 释放资源
	ois.close();
利用BeanUtils,apache和spring都提供了bean工具,它是浅克隆

扩展

  • BeanUtils 是工具类,用于简化JavaBean的封装,简化数据的封装。(xhj理解:和collections是一样的,同样是工具类)
  • apache 是 世界使用排名第一的Web服务器软件,具有跨平台和安全性的优势,是最流行的Web服务器端软件之一。
  • Spring框架是一个开放源代码的J2EE应用程序框架,针对bean的生命周期进行管理的轻量级容器。
    在Spring中,构成应用程序主干并由Spring IOC容器管理的对象称为bean。bean是一个由Spring IOC容器实例化、组装和管理的对象。
    实例的创建不再由调用者管理,而是由Spring容器创建,容器会负责控制程序之间的关系,而不是由程序代码直接控制。
浅克隆(Shallow Clone) 和 深克隆(Deep Clone)

两种克隆方式主要区别在于是否支持引用类型的成员变量的复制。
java中的数据类型分为:基本数据类型(数值型{整型、浮点型、字符型}) 和 引用数据类型(接口、类、数组)

浅克隆(Shallow Clone)

浅克隆中,对象的复制只是复制它本身和其中包含的值类型的成员变量,而引用类型的成员变量并没有复制。
实现方法
覆盖Object类中的Clone()方法实现。

1 被复制的类需要实现Cloneable接口
	public class 类名 implements Cloneable{}
2 覆盖clone()方法,方法调用super.clone()方法得到需要的复制对象,输入clone有选项可以选择,自动生成。 修改为public访问级别
	@Override
    	public Object clone() throws CloneNotSupportedException {
        	return super.clone();
    	}

实验分析:

1 被复制的类没有实现Cloneable接口,而直接使用  类名 对象2 = (类名)对象1.clone(); 会报错
	报clone()方法在java.lang.Object中是protected访问控制。
2 被复制的类实现Cloneable接口,使用 类名 对象2 = (类名)对象1.clone();  也会报错,
	需要抛出异常CloneNotSupportedException异常

案例:

// 320-test1
// 类
public class Student implements Cloneable{
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

// 测试类
public class StudentDemo {
    public static void main(String[] args) throws CloneNotSupportedException {
        Student s1 = new Student("汪苏泷",35);
        Student s2 = (Student)s1.clone();

        System.out.println(s1.getName() + ", " + s1.getAge());
        System.out.println("--------------");
        System.out.println(s2.getName() + ", " + s2.getAge());
        System.out.println(s1 == s2);// false 说明对象在堆内存中的地址不同
    }
}
深克隆(Deep Clone)

深克隆中,无论原型对象的成员变量的类型是值类型还是引用数据类型,都会复制一份给克隆对象。
实现方法:
方法一:通过覆盖Object类中的clone()方法实现

1 被复制对象的类 需要实现Cloneable接口,并重写Object类中的clone()方法。
	public class Outer implements Cloneable{
			private Inner inner;

			@Override
			public Object clone() throws CloneNotSupportedException{
				Outer obj = (Outer)super.clone(); //类对象使用clone()方法
				obj.inner = (Inner)inner.clone();//类对象属性的类 使用clone()方法
				return obj;
				}
			}
2 Inner类也要实现Cloneable接口,重写Object类中的clone()方法。
	public class Inner implements Cloneable{
		@Override
		public Object clone() throws CloneNotSupportedException{
			Inner obj = (Inner)super.clone();
		}
* 输入clone有选项可以选择 修改为public访问级别

方法二:使用序列化(Serialization)实现,序列化流ObjectOutputStream、反序列化流ObjectInputStream

// 序列化
1 创建序列化流对象
	ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("文件路径"));
2 创建对象
	类名 obj1 = new 类名();
3 使用序列化方法writeObject(Object obj)
	oos.writeObject(obj1);
4 释放资源
	oos.close();

// 反序列化
1 创建反序列化对象
	ObjectInputStream ois = new ObjectInputStream(new FileInputStream("文件路径"));
2 使用反序列化方法readObject()
	Object obj = ois.readObject();
3 强制类型转换 Object =》 类名
	类名 obj2 =(类名)obj;
4 释放资源
	ois.close();

方法一案例:

// 320-test2
// Student的属性 的类
public class Address implements Cloneable {
    private String address;

    public Address() {
    }

    public Address(String address) {
        this.address = address;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

// Student 要克隆的对象所属的类
public class Student implements Cloneable{
    private String name;
    private int age;
    private Address addr;
    // 创建的是Address类的对象

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Address getAddr() {
        return addr;
    }

    public void setAddr(Address addr) {
        this.addr = addr;
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        Student stu = (Student)super.clone();//浅克隆
        stu.addr = (Address)addr.clone();//深克隆
        return stu;

    }
}
// 测试类
public class StudentDemo {
    public static void main(String[] args) throws CloneNotSupportedException {
        Address addr = new Address("西安市");
        Student s1 = new Student("汪苏泷",35);
        s1.setAddr(addr);
        Student s2 = (Student)s1.clone();

        System.out.println(s1.getName() + ", " + s1.getAge()+", "+s1.getAddr().getAddress());
        System.out.println(s2.getName() + ", " + s2.getAge()+", " + s2.getAddr().getAddress());
//        System.out.println(s1 == s2);// false 说明对象在堆内存中的地址不同
        // 修改前输出:   汪苏泷, 35, 西安市
        //              汪苏泷, 35, 西安市

        // 两个对象的Addr变量都一样,为了验证原对象和新对象是两个不一样的,这里对s2对象的Addr变量修改值
        addr.setAddress("重庆市");
        System.out.println("修改之后");
        System.out.println("--------------");
        System.out.println(s1.getName() + ", " + s1.getAge()+", "+s1.getAddr().getAddress());
        System.out.println(s2.getName() + ", " + s2.getAge()+", " + s2.getAddr().getAddress());
        // 对s2对象的成员变量addr进行修改,s1对象的addr变量也发生了变化。
        //  =》 说明 没有实现深克隆,只完成了浅克隆,成员是值类型的复制。
        // 要想实现深克隆,需要给Student类中的addr变量所处在类Address设置为浅克隆实现。
        // Address实现cloneable、且重写clone方法

        // 修改前输出:汪苏泷, 35, 重庆市
        //           汪苏泷, 35, 重庆市
        // 修改后输出:汪苏泷, 35, 重庆市
        //           汪苏泷, 35, 西安市
    }
}
细节对比点
new操作符创建对象和clone方法复制对象的区别
具体操作newclone
分配内存根据new操作符后面的类型分配对应大小的内存空间分配与源对象相同大小的内存空间
填充对象的域调用构造方法,填充对象的各个域(对象的初始化)使用源对象中对应的各个域填充新对象的域
对象创建完毕构造方法返回创建完毕的对象,并将其引用地址发布到外部(栈内存)clone()方法返回对象,并将其引用发布到外部(栈内存)
复制引用 和 复制对象 区别

A 是 源对象,B 是 新对象
复制引用 = A 和 B 地址值 相同,说明是一个对象
复制对象 = A 和 B 地址值 不相同,说明是两个对象

克隆两种实现方式的区别
区别项实现Cloneable接口的方式序列化和反序列化方式
是否可以实现深度克隆可以,
若对象属性嵌套很多引用类型,则需要在类中写多个.clone()方法,使用不是很方便
可以,使用方便
是否支持编译时检测异常不支持,是在运行时抛出异常的支持,通过泛型限定,可以检查出克隆的对象是否支持序列化,在编译阶段完成

java参数传递 = 值传递

当java传递的参数是基本数据类型时,一个方法不能改变基本数据类型参数的值;
当java传递的参数是引用数据类型时,一个方法可以修改引用数据类型参数所指向的对象的值;
值传递的精髓:传递的是存储单元中的内容,而不是存储单元的引用。

基本数据类型参数

// idea_face-test2-TransferTest
public class TransferTest {
    public static void main(String[] args) {
        int num = 1;
        System.out.println("method()方法调用前=" + num);
        method(num);
        System.out.println("method()方法调用后=" + num);
    }
    public static void method(int number){
        number = 2;
    }
    //method()方法调用前=1
    //method()方法调用后=1
}

分析:
在这里插入图片描述
引用数据类型参数

public class TransterTest2 {
    public static void main(String[] args) {
        Person p = new Person("汪苏泷");
        System.out.println("调用方法前= name:" + p.getName());
        method(p);
        System.out.println("调用方法后= name:" + p.getName());
    }
    public static void method(Person p){
        p.setName("许嵩");
    }
    // 调用方法前= name:汪苏泷
    // 调用方法后= name:许嵩
}

分析:
在这里插入图片描述

RMI

  • RMI(Remote Method Invocation),远程方法调用,允许运行在一个java虚拟机的对象调用运行在另一个java虚拟机上的对象的方法。两个虚拟机可以是运行在相同计算机上的不同进程,也可以是运行在网络中的不同计算机。
  • RPC(Remote Procedure Call),远程过程调用,用于一个进程调用另一个进程。

Java中的动态代理

代理模式
  • 代理模式(Proxy或Surrogate),就是一个人或机构代替另一个人或机构采取行动。
    一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
    代理就是为其他对象提供一个代理以控制对某个对象的访问。
  • 优点:
    可以隐藏真实目标类的实现;可以实现客户与真实目标类之间的解耦,在不修改真实目标类代码的情况下能够做一些操作;
  • 代理模式实现条件:
    代理类和被代理类实现共同的接口(或继承);
    代理类中存在指向被代理类的索引;( xhj 这个代理类的索引 = 创建的真实类的对象 )
    实际执行是通过调用代理类的方法从而实际执行被代理类的方法。
  • 代理分类:
    静态代理:程序员创建或特定工具自动生成源码,在对其进行编译。运行前,代理类的.class文件就已经存在了;
    动态代理:程序运行时,运用反射机制动态创建而成,动态代理类的字节码文件在程序运行时由java反射机制动态生成,无需程序员手工编写它的源代码。
    • 动态代理分类:
      基于接口的代理:代表 = JDK代理
      基于继承的代理:代表 = CGlib代理
静态代理

实现步骤

1 创建一个接口MyInterface,并创建抽象方法
	public interface MyInterface{
		// 创建抽象方法
		public abstract 返回值类型 method(接口MyInterface参数);
		}
2 创建MyInterface真实的实现类RealClass,重写接口中的抽象方法
	public class RealClass implements MyInterface{
		// 重写接口中的抽象方法,此时方法不在带有abstract修饰符
		@Override
		public 返回值类型 method(接口MyInterface参数){
		  真实的实现过程;
			}
	}
3 创建 代理类
	public class ProxyClass implements MyInterface{
		// 创建接口MyInterface的实现类对象,
		// 这里创建的是接口MyInterface的真实类对象,也就是代理类中指向被代理类的索引
		private MyInterface myinterface;
		
		// 创建带参构造方法(真实类 真实类对象)
		ProxyClass(MyInterface myinterface){
			this.myinterface = myinterface;
		}
		
		// 重写接口MyInterface中的抽象类方法
		@Override
		public method(接口MyInterface参数){
			调用代理方法前做的事情;
			返回值 x = myinterface.method(接口MyInterface参数);
			调用代理方法后做的事情;
		}

理解

  • 好处:
    比如每次从磁盘中获取字体库的时候,磁盘的I/O比较耗时,想通过缓存将读到的字体库暂存一份,直接修改代理类ProxyClass,不用修改真实RealClass类。
    同样这样的需求直接修改RealClass类也可以实现,但是当多个RealClass2,RealClass3也需要判断缓存是否有字体的时候,那么修改真实类就需要修改多个,而采用代理类的形式,只需要修改一个类即可。

代码
需求:考虑一个字体提供功能,字体库可能源自本地磁盘、网络或者系统。

// 326-test1
// 接口
// 先考虑从本地磁盘中获取字体,采用代理的方式实现,定义一个提供字体的接口FontProvider:
public interface FontProvider {
    Font getFont(String name);
}
// 真实类:真正提供获取磁盘字体库的类
public class FontProviderFromDisk implements FontProvider{
    @Override
    public Font getFont(String name) {
        System.out.println("磁盘上的字体库");
        return null;
    }
    // 只是输出文字,返回值类型可以不写为Font类型,而是写为void
}
// 代理类
public class ProxyForFont implements FontProvider{
    private FontProvider fontProvider;
    // 定义一个接口对象,实际上是被代理类对象
    ProxyForFont(FontProvider fontProvider){
        this.fontProvider = fontProvider;
    }
    // 定义带参构造方法,参数为接口对象
    @Override
    public Font getFont(String name) {
        System.out.println("提供代理方法前做的事情");
        Font font = fontProvider.getFont(name);
        System.out.println("调用代理后做的事情");
        return font;
    }
}
// 测试类
public class MyFontDemo {
    public static void main(String[] args) {
        FontProvider fp = new ProxyForFont(new FontProviderFromDisk());
        // 多态的形式创建FontProvider接口对象
        // 接口 对象名 = new 代理类名(new 真实类名());
        fp.getFont("宋体");
    }
}
动态代理

出现的原因
当需要获取多种资源,比如字体、图片、音乐等资源,这时就需要多个接口,比如FontProvider、ImageProvider、MusicProvider接口等,需要对应的实现类(比如FontClass、ImageClass、MusicClass等),和其对一个的代理类(比如FontProxy、ImageProxy、MusicProxy等)。当需要给获取字体、图片、音乐等功能上加上缓存功能,就需要对三个代理类进行改动,但是修改的部分逻辑上又相同,就会造成代码的重复和代理类爆炸。
分类: 基于接口的代理(JDK) 和 基于继承的代理(CGlib)

基于接口的代理JDK

InvocationHandler接口

  • InvocationHandler接口
    每个代理类的实例都会有一个与之相关联的InvocationHandler实现类,如果代理的方法被调用,那么代理便会通知和转发给内部的 InvocationHandler 实现类,由它决定处理。
public interface InvocationHandler { // 接口
		// 唯一的方法invoke
    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
}

参数介绍:

参数名说明
Object proxy代理对象
Method method代理对象调用的方法
Object[] args调用方法中的参数

Proxy类的静态newProxyInstance方法
返回指定接口的代理实例,该代理实例将方法调用分配给指定的调用处理程序。

public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)

参数介绍:

参数名说明获得
ClassLoader loader类加载器测试类.class.getClassLoader()
Class<?>[] interfaces用来代理的接口new Class[]{接口.class}
也就是说这里可以是多个接口.class
InvocationHandler h一个InvocationHandler对象InvocationHandler handler = new jdkProxyClass(new RealSubject());
jdkProxyClass是代理类,RealSubject是真实类

说明

  • 测试类.class.getClassLoader()
    测试类.class,得到该类对应的Class类对象,通过类的class属性
    Class类对象.getClassLoader(),得到Class类对象的类加载器
  • Class<?>[] interfaces = new Class[]{接口.class}
    2022/4/25 理解:需要创建一个Class数组,成员是接口的Class对象。

具体的实现步骤

1 创建接口MyInterface
	public interface MyInterface{
		// 定义抽象方法
		public abstract 返回值类型 method1();
		public abstract 返回值类型 method2();
		}
		
2 创建真实的接口实现类RealClass
	public class RealClass{
		// 重写抽象方法
		@Override
		public 返回值类型 method1(){
			method1具体的实现;
			}
		@Override
		public 返回值类型 method2(){
			method2具体的实现;
			}
		}
		
3 创建接口的代理类,需要实现InvocationHandler接口
	public class jdkProxyClass implements InvocationHandler{
		// 创建接口的真实类对象
		private RealClass realObj;
		
		// 创建真实类对象为参数的带参构造方法
		public jdkProxyClass(RealClass realObj){
			this.realObj = realObj;
		}
		
		// 重写Object类中的invoke方法
		public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		// proxy 被代理的对象;method:调用的方法;args:方法所需的参数
			执行代理调用之前的操作。
			Object result = null;
			// 这里的方法是通过反射获取的方法对象
			result = method.invoke(realObj,args);
			return result;
	}
	
4 创建测试类
	public class jdkDemo{
		public static void main(String[] args){
			// 创建要代理的真实对象,采用多态的形式
			MyInterface realObj = new RealClass();
			// 创建代理对象
			InvocationHandler handler = new jdkProxyClass(realObj);
			// 使用Proxy.newProxyInstrace()这个静态方法 获得接口的对象
			MyInterface myinterface = (MyInterface)Proxy.newProxyInstance(jdkDemo.class.getClassLoader(),new Class[]{MyInterface.class},handler);
			// 通过接口对象调用方法
				myinterface.method1();
				myinterface.method2();
	}

案例:

// 326-test2
// 接口定义
public interface Subject {
    void method1();
    void method2();
}
// 接口真实的实现类定义
public class RealSubject implements Subject{
    @Override
    public void method1() {
        System.out.println("method1执行");
    }

    @Override
    public void method2() {
        System.out.println("method2执行");
    }
}

// 接口的代理类定义
public class jdkProxySubject implements InvocationHandler {
    // 创建代理类的真实对象,也就是真实类的对象
    private Object subject;
    // 创建带参构造方法
    public jdkProxySubject(Object subject){
        this.subject = subject;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // proxy:被代理的对象
        // method:调用的方法
        // args:方法所需要的参数
        System.out.println("before");
        Object result = null;
        try{
            // 利用反射动态的来反射方法,动态代理和静态代理的区别
            result = method.invoke(subject, args);
        }catch(Exception e){
            System.out.println("ex:" + e.getMessage());
        }finally {
            System.out.println("after");
        }
        return result;
    }
}
// 测试类
public class Client {
    public static void main(String[] args){
        // 创建要代理的真实对象
        Subject realSubject = new RealSubject();

        // 创建代理对象,将真实对象作为参数传入
        InvocationHandler handler =new jdkProxySubject(realSubject);
        Subject subject = (Subject)Proxy.newProxyInstance(Client.class.getClassLoader(), new Class[]{Subject.class}, handler);
        subject.method1();
        subject.method2();
    }
}
基于继承的代理 CGlib

概述

  • CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,为一个类创建子类,并在子类中采用方法拦截技术 拦截所有对父类方法的调用,并顺势加入横切逻辑。
    ASM是一款java字节码层面的代码分析和修改工具。
    ASM的目标是生成、转换、分析已编译的java class文件,可使用ASM工具读/写/转换JVM指令集。
  • CGlib是针对类来实现代理的,原理是对指定的业务类生成一个子类,并覆盖其中业务方法实现代理,因为采用的是继承,所以不能对final修饰的类进行代理。
    由于spring框架中的MethodInterceptor接口,目前没有学习spring框架 ,后期总结。
    参考博客
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Java RMI(远程方法调用)是一种用于在分布式系统中进行远程通信的Java API。虽然它提供了方便的远程方法调用功能,但也存在一些安全漏洞。 其中一个漏洞是未经授权的远程方法调用(Unauthorized Remote Method Invocation)。在Java RMI中,远程对象可以通过URL公开,并接受来自任何Java虚拟机的调用。如果没有正确的安全措施,攻击者可以利用这个漏洞,通过发送恶意请求来执行未经授权的远程方法调用。这可能导致敏感数据泄露、服务拒绝、远程代码执行等安全风险。 另一个漏洞是远程代码执行(Remote Code Execution)。由于Java RMI允许将类作为参数传递给远程方法调用,攻击者可以通过构建恶意类来在远程系统中执行任意代码。这可能会导致远程系统被完全控制,从而对系统进行非法操作、运行恶意软件等。 为了防止这些漏洞,应采取以下安全措施: 1.授权策略:通过使用Java RMI的安全管理器,对远程调用进行授权验证。只允许受信任的主机或用户执行远程方法调用。 2.数据验证:在接受远程方法调用之前,对传入的数据进行验证和过滤,以防止恶意输入。 3.安全传输层:使用安全通信协议(如SSL/TLS)对Java RMI进行加密,以保护数据在网络传输过程中的安全性。 4.类过滤:限制远程对象所需的类只能从特定的类路径加载,以防止远程代码执行。 总之,Java RMI漏洞存在一定的风险,但通过使用适当的安全措施可以有效地减少这些风险。 ### 回答2: Java RMI (Remote Method Invocation)是Java中用于远程调用方法的技术,它允许在不同主机上的Java虚拟机之间进行通信和交互。然而,Java RMI中存在一些漏洞,可能导致安全问题。下面是一些常见的Java RMI漏洞: 1. 未授权访问:在没有适当访问控制的情况下,攻击者可能能够直接访问Java RMI服务,获取敏感信息或执行恶意操作。 2. 服务猝死:如果不正确地实现了Java RMI服务,攻击者可能通过发送恶意请求来导致服务崩溃或拒绝服务,导致系统不可用。 3. 反序列化漏洞:由于Java RMI使用Java序列化来传输对象,因此未进行适当的反序列化验证可能导致反序列化漏洞,攻击者可以利用此漏洞在目标系统上执行任意代码。 4. 中间人攻击:由于Java RMI缺乏加密机制,攻击者可能能够拦截和篡改Java RMI通信,以获取敏感信息或篡改数据。 为了解决这些漏洞,可以采取以下措施: 1. 实施访问控制:确保只有经过授权的用户能够访问Java RMI服务,并且只有必要的方法和数据暴露给客户端。 2. 安全配置:在构建Java RMI服务时,应遵循安全最佳实践,确保已正确配置安全管理器和策略文件,以限制服务的操作和访问范围。 3. 验证和过滤输入:在处理Java RMI请求时,始终进行输入验证和过滤,以防止恶意输入和攻击。 4. 反序列化信任:避免直接反序列化不受信任的数据,可以使用白名单或其他验证机制来限制反序列化操作。 5. 加密通信:考虑使用安全的通信协议(如SSL/TLS)来保护Java RMI通信的机密性和完整性,以防止中间人攻击。 总之,了解Java RMI漏洞并采取适当的防护措施是确保Java RMI应用程序安全的重要步骤。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值