标签: classloader

正确使用Classloader(特别是在Android中)

我阅读了一些关于类加载器的文档,但我仍然不确定它们的位置和原因.Android API说:

从存储库加载类和资源.在运行时安装一个或多个类加载器.只要运行时系统需要一个尚未在内存中可用的特定类,就会查询这些内容.

因此,如果我理解这是正确的,那么可以有许多负责加载新类的classlaoders.但系统如何决定使用哪个?在哪种情况下,开发人员应该实例化一个新的类加载器?

在Intent的Android API中有一种方法

public void  setExtrasClassLoader  (ClassLoader  loader)
Run Code Online (Sandbox Code Playgroud)

描述说:

设置从此Intent的extras中解组任何Parcelable值时将使用的ClassLoader.

那么我可以定义一个特殊的类加载器,以便我可以使用未在接收活动中定义的Intent传递对象吗?一个例子:

如果位于项目A(在Eclipse中)的活动A使用Intent对象的putExtra定义了我想要发送到项目B中的活动B的对象.如果未定义通过Intent发送的此对象(项目B中的源代码),则存在NoClassDefFoundException.那么我可以使用方法setExtraClassloader来避免这种异常吗?如果是,我如何决定我必须通过哪个类加载器对象?我如何正确实例化它?

java android classloader

11
推荐指数
2
解决办法
1万
查看次数

更改类加载器

我正在尝试在运行时切换类加载器:

public class Test {
    public static void main(String[] args) throws Exception {
        final InjectingClassLoader classLoader = new InjectingClassLoader();
        Thread.currentThread().setContextClassLoader(classLoader);
        Thread thread = new Thread("test") {
            public void run() {
                System.out.println("running...");
                // approach 1
                ClassLoader cl = TestProxy.class.getClassLoader();
                try {
                    Class c = classLoader.loadClass("classloader.TestProxy");
                    Object o = c.newInstance();
                    c.getMethod("test", new Class[] {}).invoke(o);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                // approach 2
                new TestProxy().test();
            };
        };
        thread.setContextClassLoader(classLoader);
        thread.start();
    }
}
Run Code Online (Sandbox Code Playgroud)

和:

public class TestProxy {
    public void test() {
        ClassLoader …
Run Code Online (Sandbox Code Playgroud)

java reflection multithreading bcel classloader

11
推荐指数
1
解决办法
2万
查看次数

如何检查类是否已初始化?

您可能会问,为什么我要这样做 - 这是因为我正在使用一个类(来自外部库),它在静态初始化程序中执行操作,我需要知道它是否已经完成.

我看了看ClassLoader,但没有找到任何看起来有用的东西.有任何想法吗?

java classloader static-initializer

11
推荐指数
1
解决办法
9188
查看次数

java.lang.LinkageError:ClassCastException

我确实遇到过TestNG和RESTeasy的烦人问题.

我有一个类,它针对API类运行多个测试,该类使用RESTeasy框架来暴露自己.

但是,如果我让测试运行maven(mvn test),那么我得到以下异常:

java.lang.LinkageError: ClassCastException: attempting to castjar:file:/C:/Users/rit/.m2/repository/org/jboss/resteasy/jaxrs-api/2.3.0.GA/jaxrs-api-2.3.0.GA.jar!/javax/ws/rs/ext/RuntimeDelegate.classtojar:file:/C:/Users/rit/.m2/repository/org/jboss/resteasy/jaxrs-api/2.3.0.GA/jaxrs-api-2.3.0.GA.jar!/javax/ws/rs/ext/RuntimeDelegate.class
at javax.ws.rs.ext.RuntimeDelegate.findDelegate(RuntimeDelegate.java:126)
at javax.ws.rs.ext.RuntimeDelegate.getInstance(RuntimeDelegate.java:96)
at javax.ws.rs.core.Response$ResponseBuilder.newInstance(Response.java:394)
at javax.ws.rs.core.Response.status(Response.java:116)
at javax.ws.rs.core.Response.status(Response.java:130)
at com.pd.api.TokenAPI_V1.validateAccessToken(TokenAPI_V1.java:141)
at com.test.pd.api.TokenAPI_V1Test.testIfValidAccessTokenReturnsCorrectHTTPHeadersWhenTokenIsNotFound(TokenAPI_V1Test.java:359)
Run Code Online (Sandbox Code Playgroud)

测试只是调用API obejct的方法,该方法返回一个Response对象(来自RESTeasy).作为测试框架,我使用TestNG.

测试方法

@Test
public void testIfValidAccessTokenReturnsCorrectHTTPHeadersWhenTokenIsNotFound() throws InvalidAccessTokenException {
    Mockito.when(tokenService.validateAccessToken(TestConstants.ACCESS_TOKEN)).thenThrow(new InvalidAccessTokenException());

    Response response = tokenAPI_v1.validateAccessToken(TestConstants.ACCESS_TOKEN, TestConstants.USER_AGENT);
    assert "no-store".equals(response.getMetadata().getFirst("Cache-Control"));
    assert "no-cache".equals(response.getMetadata().getFirst("Pragma"));
}
Run Code Online (Sandbox Code Playgroud)

问题说明

看起来RESTeasy框架在不同的类加载器中加载RuntimeDelegate.如果我看一下源代码,那么在RuntimeDelegate(包括第126行)中有以下方法:RuntimeDelegate.java.

因此,与错误相关的主要语句是instanceof check:

if (!(delegate instanceof RuntimeDelegate))
Run Code Online (Sandbox Code Playgroud)

如果我检查委托实例的类加载器与RuntimeDelegate的类加载器,那么我得到以下输出:

delegate.getClass().getClassLoader() -> org.powermock.core.classloader.MockClassLoader@31e46a68

RuntimeDelegate.class.getClassLoader() -> sun.misc.Launcher$AppClassLoader@3c0fabe9
Run Code Online (Sandbox Code Playgroud)

我知道这当然不起作用,但我想知道为什么RESTeasy的东西被加载到MockClassLoader而不是另一个.特别是因为我没有模拟被测试的TokenAPI.

奇怪的事实

奇怪的是,当我从IntelliJ运行测试时(我选择只运行包含产生错误的方法的给定类的所有测试),然后它就会运行.看起来它与mvn测试运行maven项目中的所有测试(或者至少我认为是这样)的事实有某种关系.

java testng classloader mockito powermock

11
推荐指数
1
解决办法
1万
查看次数

有和没有getClassLoader的getResourceAsStream有什么区别?

我想知道以下两者之间的区别:

MyClass.class.getClassLoader().getResourceAsStream("path/to/my/properties");

MyClass.class.getResourceAsStream("path/to/my/properties");

谢谢.

java classloader

11
推荐指数
1
解决办法
4431
查看次数

Java:没有为jdbc:h2找到合适的驱动程序

我的一些代码存在问题,我搜索并尝试了我所知道的一切,没有任何运气.


场景:

  • 应用程序检查是否存在JDBC驱动程序,在本例中为H2驱动程序(org.h2.Driver).
  • 如果它不存在,应用程序将下载JDBC驱动程序并将其添加到ClassLoader,如下所示:( 注意:storageDataManager是我用于SQL方法的类)

       File h2Driver = new File(directory.toString() + File.separator + "lib" + File.separator + "h2.jar");
       if (h2Driver.exists()) {
           URL[] url = new URL[0];
           try {
               url = new URL[]{h2Driver.toURI().toURL()};
               storageDataManager.setClassLoader(new URLClassLoader(url));
           } catch (MalformedURLException ignore) {}
        }
    
    Run Code Online (Sandbox Code Playgroud)

当storageDataManager运行第一个查询时,它会尝试连接指定的驱动程序,如果它有一个ClassLoader,它会使用ClassLoader:

if (getClassLoader() != null) {
    getLogging().debug("Loading custom class loader for H2 driver: " + getClassLoader().toString());
    Driver driver = (Driver) Class.forName("org.h2.Driver", true, getClassLoader()).newInstance();
    getLogging().debug("Loaded H2 driver: " + driver.toString() + " - " + driver.getMinorVersion() + " - " …
Run Code Online (Sandbox Code Playgroud)

java jdbc h2 classloader

11
推荐指数
1
解决办法
2万
查看次数

具有RMI调用的ClassLoader

我试图制作简单的java分析器并使用ClassLoader.

这是我对ClassLoader的实现:

import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class CustomClassLoader extends ClassLoader {
    private Notifier notifier;

    public CustomClassLoader() {
        super();
    }

    public CustomClassLoader(ClassLoader parent) {
        super(parent);
    }

    private void initNotifier() {
        if (notifier != null) return;
        try {
            System.out.println("2");
            Registry registry = LocateRegistry.getRegistry(Const.registryPort);
            System.out.println("3");
            notifier = (Notifier) registry.lookup(Const.stubName);
            System.out.println("4");
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
    }

    @Override
    protected synchronized Class<?> loadClass(String name, boolean resolve) 
                                    throws ClassNotFoundException {
        System.out.println("0");
        Class clazz = super.loadClass(name, resolve);
        System.out.println("1");
        initNotifier();
        System.out.println("5");
        try …
Run Code Online (Sandbox Code Playgroud)

java profiler rmi classloader

11
推荐指数
1
解决办法
751
查看次数

是否可以创建指向内存中对象的URL?

我正在尝试扩展我的库以进行集成Swing,JPA并将JPA配置设置为可自动(和可移植),这意味着以编程方式添加<class>元素.(我知道它可以通过Hibernate AnnotationConfiguration或EclipseLInk 完成ServerSession,但是 - 可移植性).我也想避免Spring仅仅为了这个目的而使用.

我可以动态创建persistence.xml,并使用<class>指定包中的元素(通过Reflections库)填充它.当我尝试将此persistence.xml提供给JPA提供程序时,问题就开始了.我能想到的唯一方法是设置一个URLClassLoader,但是我想不出一种方法,首先不会让我把文件写到磁盘上,因为它有能力获得有效的URL.设置套接字通过URL(localhost:xxxx)服务文件似乎......我不知道,邪恶?

有谁知道如何解决这个问题?我知道避免使用一个库听起来很多工作,但我只想知道它是否可以完成.

编辑(尝试更清楚):

动态生成XML保存在String对象中.我不知道如何使它可用于持久性提供程序.另外,我想避免将文件写入磁盘.

出于我的问题的目的,持久性提供程序只是一个扫描类路径的类META-INF/persistence.xml.可以使一些实现接受动态创建XML,但是没有通用接口(特别是对于文件的关键部分,<class>标签).

我的想法是建立一个习俗ClassLoader- 如果你有任何其他的我会感激,我不会在这个上面.

我能找到的唯一容易扩展/可配置的是a URLClassLoader.它适用于URL对象,我不知道是否可以创建一个没有实际首先将XML写入磁盘.

这就是我正在设置的方式,但它是通过写入persistenceXmlFile = new File("META-INF/persistence.xml")磁盘来实现的:

Thread.currentThread().setContextClassLoader(
    new URLResourceClassLoader(
        new URL[] { persistenceXmlFile.toURI().toURL() },
        Thread.currentThread().getContextClassLoader()
    ) …
Run Code Online (Sandbox Code Playgroud)

java jpa classloader

11
推荐指数
1
解决办法
1898
查看次数

如何设置java类加载器PARENT_LAST

我有一个spring mvc web应用程序,我需要更改类加载器.我需要将类加载器更改为等于PARENT_LAST.我正在使用WAS 6.1并且已经有一个jacl脚本来自我之前可以复制的Web应用程序来完成这项工作.

在最后一个应用程序中使用了Apache ant,他们所做的是使部署依赖于运行jacl脚本.

在我的新Web应用程序中,我使用maven install来创建war文件,并将该war文件部署到我的应用程序服务器.

如何使用maven将类加载器设置为PARENT_LAST?我知道如何在控制台中执行此操作,但如果有办法使用脚本执行它会很好.

此设置也将放置在war文件中的某个位置,以便在部署应用程序时将获取该设置.这个问题来自于我对jacl脚本如何工作缺乏了解?

谢谢

websphere wsadmin classloader websphere-6.1 maven

11
推荐指数
1
解决办法
2万
查看次数

使用packageName和Classloader实例化JAXBContext时,会混淆ClassNotFoundException

我正在尝试使用Java中的JAXB将XML文件解组为生成的类结构.我遇到了一个令人困惑的问题,我所使用的类加载器JAXBContext.newInstance(packageName, classLoader)显然找不到一些必要的类来实例化模式类,但是当我手动搜索所提供的类加载器以获取所需的类时,它们就在那里:

URLClassLoader cl = this.getJaxbClassloader();
try 
{
    cl.loadClass("org.postgresql.util.PGInterval");
    Log.error("Found class [" + name + "] in provided classloader");
} 
catch (ClassNotFoundException e) 
{
    Log.error("Unable to find class [" + name + "]  in provided classloader");
}

JAXBContext ctx = JAXBContext.newInstance( "com.comp.gen", cl);
Run Code Online (Sandbox Code Playgroud)

getJaxbClassloader() 方法只是创建一个新的URLClassLoader,加载生成的类所需的一些特定jar,然后将系统类加载器设置为父类.生成的类使用了一些我放入类加载器的postgresql库,这是我遇到问题的资源.JAXB正确地在提供的包中找到ObjectFactory类,它只是生成的类本身的实例化,这似乎是问题所在.

运行此代码的结果是手动调用cl.loadClass("org.postgresql.util.PGInterval");工作正常,它记录第一个语句,说它找到了类,没有抛出异常.但是当JAXBContext实例化时,它会在完全相同的资源上抛出CNFE:

java.lang.ClassNotFoundException: org.postgresql.util.PGInterval
   at java.net.URLClassLoader.findClass(URLClassLoader.java:600)
   at java.lang.ClassLoader.loadClassHelper(ClassLoader.java:772)
   at java.lang.ClassLoader.loadClass(ClassLoader.java:745)
   at java.lang.ClassLoader.loadClass(ClassLoader.java:726)
   ... 78 more
Run Code Online (Sandbox Code Playgroud)

更彻底的堆栈跟踪:

java.lang.NoClassDefFoundError: org.postgresql.util.PGInterval
    at java.lang.Class.getDeclaredFieldsImpl(Native Method)
    at java.lang.Class.getDeclaredFields(Class.java:740)
    at com.sun.xml.bind.v2.model.nav.ReflectionNavigator.getDeclaredFields(ReflectionNavigator.java:249)
    at com.sun.xml.bind.v2.model.nav.ReflectionNavigator.getDeclaredFields(ReflectionNavigator.java:58)
    at com.sun.xml.bind.v2.model.impl.ClassInfoImpl.findFieldProperties(ClassInfoImpl.java:370) …
Run Code Online (Sandbox Code Playgroud)

java jaxb classloader

11
推荐指数
2
解决办法
3865
查看次数