在YARN中使用Janino和Apache Twill导致"导入的类x.y无法加载"

时间:2014-06-09 20:58:39

标签: yarn janino apache-twill

我使用Apache Twill将一个使用Janino进行动态编译类的开源项目移植到YARN。这除了最后一个错误外,效果很好。当Janino与twill一起使用时,我得到一个异常,即无法找到类,尽管Classpath中的类甚至可以使用。

我得到的例外是:

  

2014-06-09T18:30:40,093Z ERROR o.a.d.e.p.i.p.ProjectRecordBatch [zk1]   [37daf04b-7d82-4d2f-987c-59851f2aeafe:FRAG:0:0]   AbstractSingleRecordBatch:next(AbstractSingleRecordBatch.java:60) -   查询失败   org.apache.drill.exec.exception.SchemaChangeException:失败时   试图加载生成的类       在org.apache.drill.exec.physical.impl.project.ProjectRecordBatch.setupNewSchema(ProjectRecordBatch.java:243)       在org.apache.drill.exec.record.AbstractSingleRecordBatch.next(AbstractSingleRecordBatch.java:57)       在org.apache.drill.exec.physical.impl.project.ProjectRecordBatch.next(ProjectRecordBatch.java:83)       在org.apache.drill.exec.record.AbstractSingleRecordBatch.next(AbstractSingleRecordBatch.java:45)       在org.apache.drill.exec.physical.impl.limit.LimitRecordBatch.next(LimitRecordBatch.java:99)       在org.apache.drill.exec.record.AbstractSingleRecordBatch.next(AbstractSingleRecordBatch.java:45)       在org.apache.drill.exec.physical.impl.svremover.RemovingRecordBatch.next(RemovingRecordBatch.java:94)       在org.apache.drill.exec.physical.impl.ScreenCreator $ ScreenRoot.next(ScreenCreator.java:80)       在org.apache.drill.exec.work.fragment.FragmentExecutor.run(FragmentExecutor.java:104)       在java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)       at java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:615)       at java.lang.Thread.run(Thread.java:744)引起:org.apache.drill.exec.exception.ClassTransformationException:失败

为值生成转换类:

package org.apache.drill.exec.test.generated;

import org.apache.drill.exec.exception.SchemaChangeException;
import org.apache.drill.exec.expr.holders.BitHolder;
import org.apache.drill.exec.expr.holders.VarCharHolder;
import org.apache.drill.exec.ops.FragmentContext;
import org.apache.drill.exec.record.RecordBatch;
import org.apache.drill.exec.vector.RepeatedVarCharVector;
import org.apache.drill.exec.vector.VarCharVector;
import org.apache.drill.exec.vector.complex.impl.RepeatedVarCharReaderImpl;

public class ProjectorGen0 {

    RepeatedVarCharVector vv0;
    RepeatedVarCharReaderImpl reader4;
    VarCharVector vv5;

    public boolean doEval(int inIndex, int outIndex)
        throws SchemaChangeException
    {
        {
            VarCharHolder out3 = new VarCharHolder();
            complex:
            vv0 .getAccessor().getReader().setPosition((inIndex));
            reader4 .read(0, out3);
            BitHolder out8 = new BitHolder();
            out8 .value = 1;
            if (!vv5 .getMutator().setSafe((outIndex), out3)) {
                out8 .value = 0;
            }
            if (out8 .value == 0) {
                return false;
            }
        }
        {
            return true;
        }
    }

    public void doSetup(FragmentContext context, RecordBatch incoming, RecordBatch outgoing)
        throws SchemaChangeException
    {
        {
            int[] fieldIds1 = new int[ 1 ] ;
            fieldIds1 [ 0 ] = 0;
            Object tmp2 = (incoming).getValueAccessorById(RepeatedVarCharVector.class, fieldIds1).getValueVector();
            if (tmp2 == null) {
                throw new SchemaChangeException("Failure while loading vector vv0 with id: org.apache.drill.exec.record.TypedFieldId@1cf4a5a0.");
            }
            vv0 = ((RepeatedVarCharVector) tmp2);
            reader4 = ((RepeatedVarCharReaderImpl) vv0 .getAccessor().getReader());
            int[] fieldIds6 = new int[ 1 ] ;
            fieldIds6 [ 0 ] = 0;
            Object tmp7 = (outgoing).getValueAccessorById(VarCharVector.class, fieldIds6).getValueVector();
            if (tmp7 == null) {
                throw new SchemaChangeException("Failure while loading vector vv5 with id: org.apache.drill.exec.record.TypedFieldId@1ce776c0.");
            }
            vv5 = ((VarCharVector) tmp7);
        }
    }

}
  

在   org.apache.drill.exec.compile.ClassTransformer.getImplementationClass(ClassTransformer.java:302)   在   org.apache.drill.exec.ops.FragmentContext.getImplementationClass(FragmentContext.java:185)   在   org.apache.drill.exec.physical.impl.project.ProjectRecordBatch.setupNewSchema(ProjectRecordBatch.java:240)   在   org.apache.drill.exec.record.AbstractSingleRecordBatch.next(AbstractSingleRecordBatch.java:57)   在   org.apache.drill.exec.physical.impl.project.ProjectRecordBatch.next(ProjectRecordBatch.java:83)   在   org.apache.drill.exec.record.AbstractSingleRecordBatch.next(AbstractSingleRecordBatch.java:45)   在   org.apache.drill.exec.physical.impl.limit.LimitRecordBatch.next(LimitRecordBatch.java:99)   在   org.apache.drill.exec.record.AbstractSingleRecordBatch.next(AbstractSingleRecordBatch.java:45)   在   org.apache.drill.exec.physical.impl.svremover.RemovingRecordBatch.next(RemovingRecordBatch.java:94)   在   org.apache.drill.exec.physical.impl.ScreenCreator $ ScreenRoot.next(ScreenCreator.java:80)   在   org.apache.drill.exec.work.fragment.FragmentExecutor.run(FragmentExecutor.java:104)   在   java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)   在   java.util.concurrent.ThreadPoolExecutor中的$ Worker.run(ThreadPoolExecutor.java:615)   在java.lang.Thread.run(Thread.java:744)引起:   org.codehaus.commons.compiler.CompileException:第4行,第8列:   导入的类" org.apache.drill.exec.exception.SchemaChangeException"   无法载入   org.codehaus.janino.UnitCompiler.compileError(UnitCompiler.java:9014)   在org.codehaus.janino.UnitCompiler.import2(UnitCompiler.java:192)at   org.codehaus.janino.UnitCompiler.access $ 000(UnitCompiler.java:104)at at   org.codehaus.janino.UnitCompiler $ 1.visitSingleTypeImportDeclaration(UnitCompiler.java:166)   在   org.codehaus.janino.Java $ CompilationUnit $ SingleTypeImportDeclaration.accept(Java.java:171)   在org.codehaus.janino.UnitCompiler。(UnitCompiler.java:164)at   org.apache.drill.exec.compile.JaninoClassCompiler.getClassByteCode(JaninoClassCompiler.java:53)   在   org.apache.drill.exec.compile.QueryClassLoader.getClassByteCode(QueryClassLoader.java:69)   在   org.apache.drill.exec.compile.ClassTransformer.getImplementationClass(ClassTransformer.java:256)   在   org.apache.drill.exec.ops.FragmentContext.getImplementationClass(FragmentContext.java:185)   在   org.apache.drill.exec.physical.impl.project.ProjectRecordBatch.setupNewSchema(ProjectRecordBatch.java:240)   在   org.apache.drill.exec.record.AbstractSingleRecordBatch.next(AbstractSingleRecordBatch.java:57)   在   org.apache.drill.exec.physical.impl.project.ProjectRecordBatch.next(ProjectRecordBatch.java:83)   在   org.apache.drill.exec.record.AbstractSingleRecordBatch.next(AbstractSingleRecordBatch.java:45)   在   org.apache.drill.exec.physical.impl.limit.LimitRecordBatch.next(LimitRecordBatch.java:99)   在   org.apache.drill.exec.record.AbstractSingleRecordBatch.next(AbstractSingleRecordBatch.java:45)   在   org.apache.drill.exec.physical.impl.svremover.RemovingRecordBatch.next(RemovingRecordBatch.java:94)   在   org.apache.drill.exec.physical.impl.ScreenCreator $ ScreenRoot.next(ScreenCreator.java:80)   在   org.apache.drill.exec.work.fragment.FragmentExecutor.run(FragmentExecutor.java:104)   在   java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)   在   java.util.concurrent.ThreadPoolExecutor中的$ Worker.run(ThreadPoolExecutor.java:615)   在java.lang.Thread.run(Thread.java:744)

如您所见,异常的类型为SchemaChangeException,但ClassNotFoundException的内部异常为SchemaChangeException

  

第4行,第8列:导入的类   " org.apache.drill.exec.exception.SchemaChangeException"不可能   装载

所以类加载器有问题,当使用Apache Twill运行应用程序时,它会发生变化。它可以单独使用,但在这两种情况下,底层罐子都是相同的。

Apache Twill还有一个添加额外资源的功能,但添加我的jar也没有工作,而是我得到一个例外,jar已经包含在内:

  

线程中的异常" ServiceDelegate STARTING" java.lang.RuntimeException:java.util.zip.ZipException:重复条目:lib / drill-java-exec-1.0.0-m2-incubating-SNAPSHOT-rebuffed.jar

     

在com.google.common.base.Throwables.propagate(Throwables.java:160)at at   org.apache.twill.yarn.YarnTwillController.doStartUp(YarnTwillController.java:133)   在   org.apache.twill.internal.AbstractZKServiceController.startUp(AbstractZKServiceController.java:82)   在   org.apache.twill.internal.AbstractExecutionServiceController $ ServiceDelegate.startUp(AbstractExecutionServiceController.java:109)   在   com.google.common.util.concurrent.AbstractIdleService $ 1 $ 1.run(AbstractIdleService.java:43)   在java.lang.Thread.run(Thread.java:744)引起:   java.util.zip.ZipException:重复条目:   lib / drill-java-exec-1.0.0-m2-incubating-SNAPSHOT-rebuffed.jar at   java.util.zip.ZipOutputStream.putNextEntry(ZipOutputStream.java:215)   在   java.util.jar.JarOutputStream.putNextEntry(JarOutputStream.java:109)   在   org.apache.twill.internal.ApplicationBundler.copyResource(ApplicationBundler.java:347)   在   org.apache.twill.internal.ApplicationBundler.createBundle(ApplicationBundler.java:140)   在   org.apache.twill.yarn.YarnTwillPreparer.createContainerJar(YarnTwillPreparer.java:388)   在   org.apache.twill.yarn.YarnTwillPreparer.access $ 300(YarnTwillPreparer.java:106)   在   org.apache.twill.yarn.YarnTwillPreparer $ 1.call(YarnTwillPreparer.java:264)   在   org.apache.twill.yarn.YarnTwillPreparer $ 1.call(YarnTwillPreparer.java:253)   在   org.apache.twill.yarn.YarnTwillController.doStartUp(YarnTwillController.java:98)   ......还有4个

使用的基础类加载器是URLClassLoader。它是用一个空数组初始化的,但是它适用于独立应用程序,只有当它与Apache Twill一起运行时才会出现问题,它从哪里获取它应该查找的URL?我怎么检查它?

类加载器定义:

public class QueryClassLoader extends URLClassLoader {

  static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(QueryClassLoader.class);

  private final ClassCompiler classCompiler;
  private AtomicLong index = new AtomicLong(0);
  private ConcurrentMap<String, byte[]> customClasses = new MapMaker().concurrencyLevel(4).makeMap();

  public QueryClassLoader(boolean useJanino) {
    super(new URL[0]);
    if (useJanino) {
      this.classCompiler = new JaninoClassCompiler(this);
    } else {
      throw new UnsupportedOperationException("Drill no longer supports using the JDK class compiler.");
    }
  }
  ...

我可以查看的任何想法,错误发生的原因或解决方法?

1 个答案:

答案 0 :(得分:-1)

Apache Twill邮件列表中提出了同样的问题。以下是对它的讨论和建议解决方案。

http://mail-archives.apache.org/mod_mbox/twill-dev/201406.mbox/%3CCAHqY-MOa8jBYs%3DEZENxxNZg-9YGMR5SASg76P_k6%2Bm6p2L9JuQ%40mail.gmail.com%3E

在邮件内容中重复我的回答:

我不熟悉janino如何工作,但在我看来,它可能没有使用上下文ClassLoader来加载类,或者至少编译生成的类的线程没有上下文 ClassLoader设置正确。

Twill的工作方式非常简单。它创建了一个“launcher.jar”,它不依赖于任何库并在YARN容器中启动JVM,如下所示:

java -cp launcher.jar ....

因此系统类加载器没有用户/库类,只有Launcher类。

然后在Launcher.main()方法中,它使用“container.jar”文件中的所有jar + .class文件创建URLClassLoader,以加载用户TwillRunnable。它还将其设置为调用“run()”方法的线程的上下文ClassLoader。因此,如果要在与“run()”线程不同的线程中手动加载类(通过ClassLoader或Class.forName),则必须使用该线程的上下文ClassLoader或使用该线程显式构造ClassLoader。正确的父类ClassLoader。