小编fab*_*cci的帖子

通过另一个包的公共子类使用包私有类的公共方法引用时出现IllegalAccessError

昨天我在Tomcat 8上部署我的Java 8 webapp后遇到了一个有趣的问题.我不想如何解决这个问题,而是更了解为什么会发生这种情况.但是,让我们从头开始.

我有两个类定义如下:

Foo.java

package package1;

abstract class Foo {

    public String getFoo() {
        return "foo";
    }

}
Run Code Online (Sandbox Code Playgroud)

Bar.java

package package1;

public class Bar extends Foo {

    public String getBar() {
        return "bar";
    }

}
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,它们在同一个包中,并最终在同一个jar中,我们称之为commons.jar.这个jar是我的webapp的依赖(即在我的webapp的pom.xml中被定义为依赖).

在我的webapp中,有一段代码可以:

package package2;

public class Something {

    ...

    Bar[] sortedBars = bars.stream()
                           .sorted(Comparator.comparing(Bar::getBar)
                                             .thenComparing(Bar::getFoo))
                           .toArray(Bar[]::new);

    ...

}
Run Code Online (Sandbox Code Playgroud)

当它被执行时,我得到:

java.lang.IllegalAccessError: tried to access class package1.Foo from class package2.Something
Run Code Online (Sandbox Code Playgroud)

玩耍和试验我能够通过三种方式避免错误:

  1. 将Foo类更改为public而不是package-private;

  2. 将Something类的包更改为"package1"(即字面上与Foo和Bar类相同,但物理上不同的是webapp中定义的Something类);

  3. 在执行违规代码之前强制加载Foo:

    try {
        Class<?> fooClass = Class.forName("package1.Foo");
    } …
    Run Code Online (Sandbox Code Playgroud)

java maven-3 maven java-8 maven-compiler-plugin

21
推荐指数
2
解决办法
3687
查看次数

Spring Boot 可执行 jar 抛出 java.lang.ClassNotFoundException: org.apache.tomcat.util.descriptor.web.ServletDef

我创建了一个简单的测试用例,显示了我目前面临的问题。

我试图做的是手动启动从 CommandLineRunner 嵌入的 Tomcat 并手动部署文件系统上某处可用的 war 文件:

package example;

import java.io.File;

import org.apache.catalina.Context;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.startup.Tomcat;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
public class MyCommandLineRunner implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {

        File tomcatBaseDir = new File("<tomcat-base-dir>");
        File warToBeDeployed = new File("<war-to-be-deployed>");

        Tomcat tomcat = new Tomcat();
        tomcat.setPort(8080);
        tomcat.setBaseDir(tomcatBaseDir.getAbsolutePath());
        tomcat.getHost().setAppBase(tomcatBaseDir.getAbsolutePath());
        tomcat.getHost().setAutoDeploy(true);
        tomcat.getHost().setDeployOnStartup(true);

        try {
            tomcat.start();
            System.out.println("Tomcat started on " + tomcat.getHost());
        } catch (LifecycleException e) {
            System.err.println("Tomcat could not be started");
            System.exit(-1);
        }

        Context appContext …
Run Code Online (Sandbox Code Playgroud)

java maven spring-boot spring-boot-maven-plugin

5
推荐指数
1
解决办法
6774
查看次数

使用 HK2 在泛型类中注入类型参数

我目前正在使用 HK2 2.5.0-b05(这是 Jersey 2.24 使用的版本),并且无法执行特定类型的注入。我能够概括我的问题,并提出一个简单的小型测试用例。

代码如下:

package com.github.fabriziocucci.test;

import javax.inject.Inject;

import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.hk2.api.ServiceLocatorFactory;
import org.glassfish.hk2.api.TypeLiteral;
import org.glassfish.hk2.utilities.ServiceLocatorUtilities;
import org.glassfish.hk2.utilities.binding.AbstractBinder;

public class Test {

    private static class A<T> {

        private final T t;

        @Inject
        public A(T t) {
            this.t = t;
            System.out.println(t);
        }

    }

    private static class B {

    }

    public static void main(String[] args) {
        ServiceLocator serviceLocator = ServiceLocatorFactory.getInstance().create(null);
        ServiceLocatorUtilities.bind(serviceLocator, new AbstractBinder() {
            @Override
            protected void configure() {
                bind(B.class).to(B.class);
                bindAsContract(new TypeLiteral<A<B>>() {}); // <--- ???
            }
        });

        serviceLocator.getService(new …
Run Code Online (Sandbox Code Playgroud)

java jersey hk2

3
推荐指数
1
解决办法
2467
查看次数