java - 无法加载 groovy 类

标签 java jenkins serialization groovy

我正在尝试使用 jenkins 管道中的以下类序列化和反序列化一个 groovy 对象。

SerializationUtil.groovy


package com.sample;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

/**
 * A simple class with generic serialize and deserialize method implementations
 */
public class SerializationUtil {

    // deserialize to Object from given file
    public static Object deserialize(String fileName) throws IOException,
            ClassNotFoundException {
        FileInputStream fis = new FileInputStream(fileName);
        ObjectInputStream ois = new ObjectInputStream(fis);
        Object obj = ois.readObject();
        ois.close();
        System.out.println(obj);
        return obj;
    }

    // serialize the given object and save it to file
    public static void serialize(Object obj, String fileName)
            throws IOException {
        FileOutputStream fos = new FileOutputStream(fileName);
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(obj);

        fos.close();
    }

}

Test.groovy


package com.sample;

public class Test implements Serializable {
    String key;

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    @Override
    public String toString() {
        return "com.sample.Test{" +
                "key='" + key + '\'' +
                '}';
    }
}

Jenkins pipeline script


Test test = new Test()
test.setKey("sample")
SerializationUtil.serialize(test,"/temp/test.txt")
Test test2 = SerializationUtil.deserialize("/temp/test.txt")

我能够序列化对象但不能反序列化。我收到以下异常。
java.lang.ClassNotFoundException: com.sample.Test
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at org.eclipse.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:543)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:348)
    at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:628)
    at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1620)
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1521)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1781)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1353)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:373)
    at sun.reflect.GeneratedMethodAccessor8862.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1213)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1022)
    at org.codehaus.groovy.runtime.callsite.PojoMetaClassSite.call(PojoMetaClassSite.java:47)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
    at com.cloudbees.groovy.cps.sandbox.DefaultInvoker.methodCall(DefaultInvoker.java:20)
    at com.sample.SerializationUtil.deserialize(SerializationUtil.groovy:20)

从异常中,我可以看到 GroovyClassLoader 没有被调用,我认为这可能是问题所在。

最佳答案

问题是,正如您已经确定的,没有 GroovyClassLoader 参与其中……特别是不知道您当前的类的人。

虽然 ObjectOutputStream 并不真正关心用 ObjectInputStream 定义的类是什么类加载器,但在这里必须做出假设,因为它需要创建一个实例。从跟踪来看,为创建对象实例而选择的“最近”类加载器将是包含 groovy 运行时的类加载器。遗憾的是,这是 Groovy 的一个常见问题,因为在 Java 中不断引入越来越多的调用者敏感逻辑。

无论如何,如果你也有这样的东西(ScriptLoaderObjectInputStream.groovy):

class ScriptLoaderObjectInputStream extends ObjectInputStream {
  ScriptLoaderObjectInputStream(InputStream str) { super(str) }

  protected Class resolveClass(ObjectStreamClass desc) {
    return this.class.classLoader.loadClass(desc.getName())
  }
}

并用这个替换您对 ObjectInputStream 的使用,它应该可以工作。它应该可以工作,因为这也是一个脚本文件,并且生成的类应该具有与其他生成的类相同的类加载器。

为了进一步阅读,我发现这个很不错:https://rsankarx.wordpress.com/2012/06/08/java-serialization-classloaders/

免责声明:我在这里写的,没有 IDE,没有拼写检查,也没有涉及测试。

关于java - 无法加载 groovy 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62166870/

相关文章:

java - IntelliJ IDEA 不会在 Debug模式下停止断言

jenkins - jenkins 中没有 Sonar 运行选项?

maven - 指定要运行的 Junit 测试

c# - 如何在 C# 中获取异步 TCP 对象流?

java.lang.IllegalArgumentException : setAttribute: Non-serializable attribute with name

java - 使用 java 发送 CTRL B

java - 插入、包含、删除和按索引获取元素的时间常数的数据结构

java - 在 AChartEngine 中为堆叠图设置 Android Toast

java - Selenium Jenkins Linux TestNG - 如何运行?

c# - 如何将包含 ILIST 成员的对象序列化为 XML?