2014-06-09 6 views
0

Apache Twill을 사용하여 Janino를 클래스의 동적 컴파일에 사용하는 Yarn에 이식합니다. 이것은 하나의 마지막 오류를 제외하고는 훌륭하게 작동합니다. Janino가 능직과 함께 사용될 때 Classpath에 클래스가 있지만 사용 된 경우에도 클래스를 찾을 수 없다는 예외가 발생합니다.Apache Twill을 사용하여 Yarn의 Janino를 사용하면 "가져온 클래스 x.y를로드 할 수 없습니다."

내가 갖는 예외입니다 :

2014-06-09T18 : 30 : 40,093Z 오류 oadepipProjectRecordBatch [zk1] [37daf04b-7d82-4d2f-987c-59851f2aeafe : 파편 : 0 : 0] AbstractSingleRecordBatch : 다음 (AbstractSingleRecordBatch.java:60) - 쿼리 org.apache.drill.exec.exception.SchemaChangeException 동안 실패 : 가 org.apache.drill.exec.physical에서 생성 된 클래스 를로드하는 동안 실패 프로젝트 관리 ec.record.AbstractSingleRecordBatch.next (AbstractSingleRecordBatch.java:57) at org.apache.drill.exec.physical.impl.project.ProjectRecordBatch.next (ProjectRecordBatch.java:83) at 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) at org.apache.drill.exec.physical.impl.svremover.RemovingRecordBatch.next (RemovingRecordBatch.java:94) at org.apache.drill.exec.physical.impl. ScreenCreator $ ScreenRoot.next (ScreenCreator.java:80) at org.apache.drill.exec.work.fragment.FragmentExecutor.run (FragmentExecutor.java:104) at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor $ Worker.run (ThreadPoolExecutor.java:615) at java.lang.Thread.run (Thread. 자바 : 744)에 의해 발생 : org.apache.drill.exec.exception.ClassTransformationException : 오류 값

생성하는 변환 클래스를 org.apache.drill.exec에서

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: [email protected]"); 
      } 
      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: [email protected]"); 
      } 
      vv5 = ((VarCharVector) tmp7); 
     } 
    } 

} 

.compile.ClassTransformer.getImplementationClass (ClassTransformer.java:302) org.apache.drill.exec.physical.impl.project.ProjectRecordBatch.setupNewSchema에서 org.apache.drill.exec.ops.FragmentContext.getImplementationClass (FragmentContext.java:185) 에서(ProjectRecordBatch.java:240) org.apache.drill.exec.physical.impl.project.ProjectRecordBatch.next에서 org.apache.drill.exec.record.AbstractSingleRecordBatch.next (AbstractSingleRecordBatch.java:57) 에서 (ProjectRecordBatch.java:83) org.apache.drill.exec.physical.impl.limit.LimitRecordBatch.next에서 org.apache.drill.exec.record.AbstractSingleRecordBatch.next (AbstractSingleRecordBatch.java:45) 에서 (LimitRecordBatch.java:99) org.apache.drill.exec.physical.impl.svremover.RemovingRecordBatch.next (RemovingRecordBatch.java:94)에서 org.apache.drill.exec.record.AbstractSingleRecordBatch.next (AbstractSingleRecordBatch.java:45) 에서 at org.apache.drill.exec.physical.impl.ScreenCreator $ ScreenRoot.next (ScreenCreator.java:80) at org.apache. java.util.concurrent.ThreadPoolExecutor $ 노동자에 drill.exec.work.fragment.FragmentExecutor.run java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1145)에서 (FragmentExecutor.java:104) . org.codehaus.commons.compiler.CompileException : Line 4, Column 8 : 가져온 클래스 "org. apache.drill.exec.exception.SchemaChangeException " 을 (를) 에로드하지 못했습니다. org.codehaus.janino.UnitCompiler.compileError (UnitCompiler.java:9014) at org.codehaus.janino.UnitCompiler.import2 (UnitCompiler.java:192) at org.codehaus.janino.UnitCompiler.access $ 000 (UnitCompiler. org.codehaus.janino.Java $ CompilationUnit $ SingleTypeImportDeclaration.accept (Java.java:171) 조직에서의 org.codehaus.janino.UnitCompiler $ 1.visitSingleTypeImportDeclaration (UnitCompiler.java:166) 104) 자바. codehaus.janino.UnitCompiler. (UnitCompiler.java:164) org.apache.drill.exec.compile.JaninoClassCompiler.getClassByteCode (JaninoClassCompiler.java:53) org.apache.drill.exec.compile.QueryClassLoader에서 에서. getClassByteCode org.apache.drill.exec.ops.FragmentContext.getImplementationClass에서 org.apache.drill.exec.compile.ClassTransformer.getImplementationClass (ClassTransformer.java:256)에서 (QueryClassLoader.java:69) (FragmentContext. java : 185) org.apache.drill.exec.record.AbstractSingleRecordBatch.next에서 org.apache.drill.exec.physical.impl.project.ProjectRecordBatch.setupNewSchema (ProjectRecordBatch.java:240) 에서 516,(AbstractSingleRecordBatch.java:57) org.apache.drill.exec.record.AbstractSingleRecordBatch.next에서 org.apache.drill.exec.physical.impl.project.ProjectRecordBatch.next (ProjectRecordBatch.java:83) 에서 (AbstractSingleRecordBatch.java:45) org.apache.drill.exec.record.AbstractSingleRecordBatch.next에서 org.apache.drill.exec.physical.impl.limit.LimitRecordBatch.next (LimitRecordBatch.java:99) 에서 (AbstractSingleRecordBatch.java:45) at org.apache.drill.exec.physical.impl.svremover.RemovingRecordBatch.next (RemoveRecordBatch.java:94) at org.apache.drill.exec.physical.impl.ScreenCreator $ ScreenRoot.next (ScreenCreator. 자바 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 java.lang.Thread.run (Thread.java:744)에서 (ThreadPoolExecutor.java:615)

당신이 볼 수 S, 예외의 유형은 SchemaChangeException하지만 내부 예외가있는 ClassNotFoundExceptionSchemaChangeException에 대한 :

4 호선, 열 8 : 수입 클래스 "org.apache.drill.exec.exception.SchemaChangeException" 수 없습니다 로드

그래서 아파치 능 능이 응용 프로그램을 실행할 때 변경되는 클래스 로더에 문제가 있습니다. 그것은 독립적으로 작동하지만 두 경우 모두 기본 항아리가 동일합니다.스레드에서

예외 "ServiceDelegate을 :

아파치 능도 추가 리소스를 추가 할 수있는 기능을 가지고 있지만, 하나가 작동하지 않았다가 내 항아리를 추가하는 대신에 나는 단지가 이미 포함되어 있는지, 예외를 얻었다 STARTING "java.lang.RuntimeException : java.util.zip.ZipException : 중복 항목 : lib/drill-java-exec-1.0.0-m2-incubating-SNAPSHOT-rebuffed.jar

at com.google.common .base.Throwables.propagate (Throwables.java:160) at org.apache.twill.yarn.YarnTwillController.doStartUp (YarnTwillController.java:133) at com.google.common에서 org.apache.twill.internal.AbstractExecutionServiceController $ ServiceDelegate.startUp (AbstractExecutionServiceController.java:109) 에서org.apache.twill.internal.AbstractZKServiceController.startUp (AbstractZKServiceController.java:82) .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) at java.util.jar.JarOutputStream.putNextEntry (JarOutputStream.java:109) org.apache.twill에서 org.apache.twill.internal.ApplicationBundler.copyResource org.apache.twill.internal.ApplicationBundler.createBundle (ApplicationBundler.java:140)에서 (ApplicationBundler.java:347)에서 63,210 .yarn.YarnTwillPreparer.createContainerJar (YarnTwillPreparer.java:388) org.apache.twill.yarn.YarnTwillPreparer.access $ (300) (YarnTwillPreparer.java:106) 에서 에서 org.apache.twill.yarn.YarnTwillPreparer $ 1.call org.apache.twill.yarn.YarnTwillController.doStartUp에서 org.apache.twill.yarn.YarnTwillPreparer $ 1.call이 (YarnTwillPreparer.java:253)에서 (YarnTwillPreparer.java:264) (YarnTwillContro ller.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

동일한 질문이 Apache Twill 메일 링리스트에서 요청되었습니다. 다음은 그것에 대한 토론과 제안 된 해결책입니다.

내가 어떻게 JANINO 작품에 익숙하지 않은,하지만 최소한으로 클래스를로드 컨텍스트 클래스 로더를 사용하지 않을 수 있다는 것을 나에게 보인다 나 :

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

은 메일 내용에 내 대답을 반복 생성 된 클래스를 컴파일하는 스레드에 문맥이 없습니다. ClassLoader가 올바르게 설정되었습니다.

능직이 작동하는 방식은 매우 간단합니다. 그것은 어떤 라이브러리에 대한 종속성이없는 "launcher.jar"를 생성하고이 같은 원사 컨테이너에 JVM을 시작합니다

java -cp launcher.jar .... 

따라서 시스템 클래스 로더에는 사용자/라이브러리 클래스,하지만 런처 클래스가 없습니다 .

그런 다음 Launcher.main() 메서드에서 "container.jar"파일 내의 모든 jars + .class 파일을 사용하여 URLClassLoader을 만들고 사용자 TwillRunnable을로드합니다. 또한 "run()"메서드를 호출하는 스레드의 컨텍스트 ClassLoader로 설정합니다. 따라서 "run()"스레드와 다른 스레드에서 클래스 (ClassLoader 또는 Class.forName을 통해)를 수동으로로드하려면 해당 스레드의 컨텍스트 ClassLoader를 설정하거나 명시 적으로 ClassLoader를 올바른 부모 ClassLoader.

+0

네, 저에게 질문을 받았지만 문제를 해결했습니다. :) – peter