简体   繁体   English

无法加载 groovy 类

[英]Unable to load a groovy classes

I am trying to serialize and deserialize a groovy object with the below class in the jenkins pipeline.我正在尝试序列化和反序列化 groovy object 在 ZAB63A76362C3972AC83D5CB81 管道中使用以下 class

SerializationUtil.groovy序列化Util.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测试.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 Jenkins 管道脚本

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

I was able to serialize the object but not deserialize.我能够序列化 object 但不能反序列化。 I am getting the below exception.我收到以下异常。

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)

From the exception, I could see that GroovyClassLoader is not called and I assume that might be the issue.从异常中,我可以看到 GroovyClassLoader 没有被调用,我认为这可能是问题所在。

The problem is, as you have identified already, that no GroovyClassLoader gets involved... specifically not the one knowing your current classes.问题是,正如您已经确定的那样,没有 GroovyClassLoader 参与其中……特别是不知道您当前类的那个。

While an ObjectOutputStream does not really care what classloader a class was defined with the ObjectInputStream has to make assumptions here, since it needs to create an instance.虽然 ObjectOutputStream 并不真正关心 class 是用什么类加载器定义的,但 ObjectInputStream 必须在这里做出假设,因为它需要创建一个实例。 Judging from the trace the "nearest" ClassLoader that woulde be selected for the object instance creation would be the class loader containing the groovy runtime.从跟踪来看,将为 object 实例创建选择的“最近”类加载器将是包含 groovy 运行时的 class 加载器。 Sadly that is a common problem with Groovy, as the keep introducing more and more caller sensitive logic in Java.可悲的是,这是 Groovy 的一个常见问题,因为在 Java 中不断引入越来越多的调用者敏感逻辑。

Anyway, if you also have something like this (ScriptLoaderObjectInputStream.groovy):无论如何,如果你也有这样的东西(ScriptLoaderObjectInputStream.groovy):

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

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

and replace your usage of ObjectInputStream with this one, it should work.并用这个替换你对 ObjectInputStream 的使用,它应该可以工作。 It should work, because this is a script file as well and the resulting class should have the same class loader your other generated classes get.它应该可以工作,因为这也是一个脚本文件,并且生成的 class 应该具有与其他生成的类相同的 class 加载器。

For further reading I find this one quite nice: https://rsankarx.wordpress.com/2012/06/08/java-serialization-classloaders/为了进一步阅读,我发现这个非常好: https://rsankarx.wordpress.com/2012/06/08/java-serialization-classloaders/

DISCLAIMER: I wrote this here, no IDE, no spell checking and no testing got involved.免责声明:我在这里写了这个,没有 IDE,没有拼写检查和测试。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM