Jdk16中JcTree的使用问题

因为jdk16进行了强制的模块化使用限制, 需要增加add-opens去进行模块的放开, 但是如果每次都需要在项目pom文件或者启动命令中增加,非常不优雅。而且很多重复的命令。
所以想有没有更好的办法去解决。
看了lombok1.18.20中的解决方法,这边来总结一下。lombok这个问题的讨论

public abstract class Example extends AbstractProcessor {
    @Override
    public final synchronized void init(ProcessingEnvironment processingEnv) {
    }
    public static void addOpens() {
        Class<?> cModule;
        try {
            cModule = Class.forName("java.lang.Module");
        } catch (ClassNotFoundException e) {
            return; //jdk8-; this is not needed.
        }

        Unsafe unsafe = getUnsafe();
        Object jdkCompilerModule = getJdkCompilerModule();
        Object ownModule = getOwnModule();
        String[] allPkgs = {
            "com.sun.tools.javac.code",
            "com.sun.tools.javac.comp",
            "com.sun.tools.javac.file",
            "com.sun.tools.javac.main",
            "com.sun.tools.javac.model",
            "com.sun.tools.javac.parser",
            "com.sun.tools.javac.processing",
            "com.sun.tools.javac.tree",
            "com.sun.tools.javac.util",
            "com.sun.tools.javac.jvm",
            "com.sun.tools.javac.api",
            };

        try {
            Method m = cModule.getDeclaredMethod("implAddOpens", String.class, cModule);
            long firstFieldOffset = getFirstFieldOffset(unsafe);
            unsafe.putBooleanVolatile(m, firstFieldOffset, true);
            for (String p : allPkgs) {
                m.invoke(jdkCompilerModule, p, ownModule);
            }
        } catch (Exception ignore) {}
    }

    private static Unsafe getUnsafe() {
        try {
            Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
            theUnsafe.setAccessible(true);
            return (Unsafe) theUnsafe.get(null);
        } catch (Exception e) {
            return null;
        }
    }

    private static Object getJdkCompilerModule() {
        try {
            Class<?> cModuleLayer = Class.forName("java.lang.ModuleLayer");
            Method mBoot = cModuleLayer.getDeclaredMethod("boot");
            Object bootLayer = mBoot.invoke(null);
            Class<?> cOptional = Class.forName("java.util.Optional");
            Method mFindModule = cModuleLayer.getDeclaredMethod("findModule", String.class);
            Object oCompilerO = mFindModule.invoke(bootLayer, "jdk.compiler");
            return cOptional.getDeclaredMethod("get").invoke(oCompilerO);
        } catch (Exception e) {
            return null;
        }
    }

    private static Object getOwnModule() {
        try {
            Method m = Permit.getMethod(Class.class, "getModule");
            return m.invoke(BaseProcessor.class);
        } catch (Exception e) {
            return null;
        }
    }

    private static long getFirstFieldOffset(Unsafe unsafe) {
        try {
            return unsafe.objectFieldOffset(Parent.class.getDeclaredField("first"));
        } catch (NoSuchFieldException e) {
            // can't happen.
            throw new RuntimeException(e);
        } catch (SecurityException e) {
            // can't happen
            throw new RuntimeException(e);
        }
    }

    public static class Parent {
        boolean first;
    }
}

其中调用了

long firstFieldOffset = getFirstFieldOffset(unsafe);
unsafe.putBooleanVolatile(m, firstFieldOffset, true);

其中的含义不太能清楚,看起来是个激活模块的初始化操作,去除之后添加模块权限的操作是会失效的。

有懂的大佬希望可以告知一下是不是这样

在注解解析器中添加上诉代码后就可以正常在java16中使用jcTree啦

Wish.

Do.

原文链接:https://www.cnblogs.com/my1024/p/17382868.html

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Jdk16中JcTree的使用问题 - Python技术站

(0)
上一篇 2023年5月9日
下一篇 2023年5月9日

相关文章

  • Spring Security前后分离校验token的实现方法

    我会详细讲解“Spring Security前后分离校验token的实现方法”的完整攻略。这里将分为以下几个步骤: 获得token 将token保存到请求头中 在后端进行token校验 返回结果给前端 下面我们具体来看一下每一步的实现方法。 1. 获得token 首先,我们需要在前端登录成功之后,获得token。我们可以通过发送登录请求来获取token,例如…

    Java 2023年5月20日
    00
  • JSP经典学习笔记(包含各种入门常用语法)

    JSP经典学习笔记攻略 JSP即Java Server Pages,是一种基于 Java 技术的Web应用程序开发技术。它允许开发者在网页中嵌入 Java 代码片段,实现与动态数据交互的功能。本篇攻略将包括以下几个部分: JSP基础语法 JSP内置对象 JSP标准标签库 两条示例说明 JSP基础语法 JSP文件结构 在JSP文件中,可以使用HTML标记和Ja…

    Java 2023年6月15日
    00
  • Java使用JDBC驱动连接MySQL数据库

    以下是Java使用JDBC驱动连接MySQL数据库的完整攻略: 1. 下载JDBC驱动 首先,我们需要下载合适的JDBC驱动程序。可以在官方网站下载最新的JDBC驱动程序。下载后将其解压缩到本地磁盘。 2. 创建MySQL数据库 我们需要在本地的MySQL数据库中创建一个数据库供使用。如果您的系统中尚未安装MySQL数据库,需要在官方网站下载并安装,安装过程…

    Java 2023年5月19日
    00
  • springboot注入servlet的方法

    下面是详细讲解Spring Boot注入Servlet的方法的完整攻略。 1. 添加Servlet API依赖 在Spring Boot中使用Servlet必须要先添加Servlet API依赖。可以在pom.xml文件中添加以下依赖项: <dependency> <groupId>javax.servlet</groupId&…

    Java 2023年5月19日
    00
  • javaWeb实现简单文件上传

    下面是“javaWeb实现简单文件上传”的完整攻略。 一、准备工作 在开始之前,需要准备以下工作: 一个支持Servlet、JavaServer Pages(JSP)的JavaWeb环境,如Tomcat、Jetty等。 一个用于上传文件的HTML表单。 编写Java Servlet程序来处理上传文件,并保存在服务器上。 二、HTML表单 HTML表单必须包含…

    Java 2023年5月20日
    00
  • Java中的异常处理机制是什么?

    Java中的异常处理机制是通过try-catch语句块和throw抛出异常语句实现的。以下是Java中异常处理机制的详细步骤: 1. 什么是异常 在编写程序时,不可避免遇到一些非预期的错误,这些错误被成为异常。Java中的异常是一种对象,它用来信号某个方法出现了错误,有关这种错误的信息被封装在异常对象中并传递给调用该方法的程序。 2. 异常分类 Java中的…

    Java 2023年4月27日
    00
  • Java实现分布式系统限流

    Java实现分布式系统限流攻略 本文主要介绍如何在Java分布式系统中实现限流功能。限流是一种保护系统稳定性的重要手段,可以有效地避免系统被过量流量攻击、系统资源被耗尽等问题。 什么是限流? 限流是一种系统资源保护机制,通过对系统请求流量进行控制,保证系统能够承受的负载范围内运行。限流可以在短时间内有效地防止系统被过量流量冲垮,保障系统的可用性和稳定性。 常…

    Java 2023年5月30日
    00
  • SpringBoot 表单提交全局日期格式转换器实现方式

    下面我将详细讲解“SpringBoot 表单提交全局日期格式转换器实现方式”的完整攻略。 一、需求及问题描述 在开发web应用时,我们经常需要处理日期格式数据。而在SpringBoot中,一般使用RestController来接收和处理表单提交的数据。但是,当表单数据中包含日期字符串时,如果格式不正确,就会抛出异常。为了解决这个问题,我们可以通过全局日期格式…

    Java 2023年6月2日
    00
合作推广
合作推广
分享本页
返回顶部