2016-12-05 3 views
1

getRecordWriterメソッドを上書きするカスタムParquetOutputFormat(クラスはorg.apache.parquet.hadoop)を作成しました。 getRecordWriterメソッド内ではCodecFactoryにアクセスし、IllegalAccessErrorが発生しています。問題を修正しようとすると、私自身のクラスローダーを作成しようとしましたが、これは役に立ちませんでした。動的クラスローダーのIllegalAccessError

override def createOutputFormat: OutputFormat[Void, InternalRow] with Ext = new CustomParquetOutputFormat[InternalRow]() with Ext { 
... 
} 

CustomParquetOutputFormatgetRecordWriterが呼び出されたときに、ライン274上CodecFactoryにアクセスしようとしたときに問題が起こる:私は、次のようCustomParquetOutputFormatを使用したカスタムクラスローダを作成する前に、私はこのブログの記事にhttp://techblog.applift.com/upgrading-spark#advanced-case-parquet-writer

を追っ

CodecFactory codecFactory = new CodecFactory(conf); 

(これはアクセスをCustomParquetOutputFormat ParquetOutputFormatのライン274である)

CodecFactoryはパッケージプライベートです。

カスタムクラスローダ:

class CustomClassLoader(urls: Array[URL], parent: ClassLoader, whiteList: List[String]) 
    extends ChildFirstURLClassLoader(urls, parent) { 
    override def loadClass(name: String) = { 
    if (whiteList.exists(name.startsWith)) { 
     super.loadClass(name) 
    } else { 
     parent.loadClass(name) 
    } 
    } 
} 

用途:

val sc: SparkContext = SparkContext.getOrCreate() 
val cl: CustomClassLoader = new CustomClassLoader(sc.jars.map(new URL(_)).toArray, 
    Thread.currentThread.getContextClassLoader, List(
    "org.apache.parquet.hadoop.CustomParquetOutputFormat", 
    "org.apache.parquet.hadoop.CodecFactory", 
    "org.apache.parquet.hadoop.ParquetFileWriter", 
    "org.apache.parquet.hadoop.ParquetRecordWriter", 
    "org.apache.parquet.hadoop.InternalParquetRecordWriter", 
    "org.apache.parquet.hadoop.ColumnChunkPageWriteStore", 
    "org.apache.parquet.hadoop.MemoryManager" 
)) 


cl.loadClass("org.apache.parquet.hadoop.CustomParquetOutputFormat") 
    .getConstructor(classOf[String], classOf[TaskAttemptContext]) 
    .newInstance(fullPathWithoutExt, taskAttemptContext) 
    .asInstanceOf[OutputFormat[Void, InternalRow] with ProvidesExtension] 

エラー:

java.lang.IllegalAccessError: tried to access class org.apache.parquet.hadoop.CodecFactory from class org.apache.parquet.hadoop.customParquetOutputFormat 
     at org.apache.parquet.hadoop.CustomParquetOutputFormat.getRecordWriter(CustomParquetOutputFormat.scala:40) 
     at org.apache.parquet.hadoop.ParquetOutputFormat.getRecordWriter(ParquetOutputFormat.java:262) 
     at org.apache.spark.custom.hadoop.HadoopWriter.<init>(HadoopWriter.scala:35) 
     at org.apache.spark.sql.execution.datasources.parquet.ParquetWriter.<init>(ParquetWriter.scala:16) 
     at org.apache.spark.sql.execution.datasources.parquet.ParquetWriterFactory.createWriter(ParquetWriterFactory.scala:71) 
     at com.abden.custom.index.IndexBuilder$$anonfun$4.apply(IndexBuilder.scala:55) 
     at com.abden.custom.index.IndexBuilder$$anonfun$4.apply(IndexBuilder.scala:54) 
     at scala.collection.immutable.Stream.map(Stream.scala:418) 
     at com.abden.custom.index.IndexBuilder.generateTiles(IndexBuilder.scala:54) 
     at com.abden.custom.index.IndexBuilder.generateLayer(IndexBuilder.scala:155) 
     at com.abden.custom.index.IndexBuilder.appendLayer(IndexBuilder.scala:184) 
     at com.abden.custom.index.IndexBuilder$$anonfun$appendLayers$1$$anonfun$apply$1.apply(IndexBuilder.scala:213) 
     at com.abden.custom.index.IndexBuilder$$anonfun$appendLayers$1$$anonfun$apply$1.apply(IndexBuilder.scala:210) 
     at scala.collection.Iterator$class.foreach(Iterator.scala:742) 
     at com.abden.custom.util.SplittingByKeyIterator.foreach(SplittingByKeyIterator.scala:3) 
     at com.abden.custom.index.IndexBuilder$$anonfun$appendLayers$1.apply(IndexBuilder.scala:210) 
     at com.abden.custom.index.IndexBuilder$$anonfun$appendLayers$1.apply(IndexBuilder.scala:209) 
     at org.apache.spark.rdd.RDD$$anonfun$foreachPartition$1$$anonfun$apply$33.apply(RDD.scala:920) 
     at org.apache.spark.rdd.RDD$$anonfun$foreachPartition$1$$anonfun$apply$33.apply(RDD.scala:920) 
     at org.apache.spark.SparkContext$$anonfun$runJob$5.apply(SparkContext.scala:1858) 
     at org.apache.spark.SparkContext$$anonfun$runJob$5.apply(SparkContext.scala:1858) 
     at org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:66) 
     at org.apache.spark.scheduler.Task.run(Task.scala:89) 
     at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:227) 
     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
     at java.lang.Thread.run(Thread.java:745) 

エラーが発生しましたgetRecordWriterこの行で:それは、そのパッケージに制限されているので、

val codecFactory = new CodecFactory(conf) 

CodecFactory修飾子がありません。同じクラスローダーからすべてのクラスをロードする動的クラスローダーを使用しても、私はまだそれを取得します。IllegalAccessError

+2

をそれはエラーメッセージが 'customParquetOutputFormat'示していることを奇妙です(小文字のc)、それ以外はすべて 'CustomParquetOutputFormat'(大文字のC)を参照します。それに加えて、 'super.loadClass(name)'は親ローダを最初にチェックし、親がそれを見つけられなかった場合にのみクラスをローカルで解決しようとすることに注意してください。さて、異なるクラスローダによってロードされたクラスは、名前に関係なく、常に異なる(実行時の)パッケージとみなされます。 – Holger

+0

申し訳ありません、エラーメッセージを修正しました。私はこの質問のクラスの名前を変更し、誤って小文字を使用しました – abden003

+0

こんにちは、以前に持っていた問題を理解するためにカスタムクラスローダーの前にあなたのコードを共有することはできますか?あなた自身のクラスローダーを実装することはここでは過度であるようです... – loicmathieu

答えて

1

Javaの仕組みを破壊しようとしています! JVMの保護ルールを破ることを可能にする独自のクラスローダーを実装することによって、パッケージ外のパッケージであるクラスにアクセスしたい(Java言語仕様を壊したい!

私の答えは簡単です:これをしないでください!

パッケージがプライベートであればアクセスできません。期間!

私は、あなたが必要とする機能と、現在のAPIを使用して実装するのが最も良いと思うのです。技術的なハッキングを行う方法を尋ねるのではなく、何をしたいのですか(なぜあなた自身のgetRecordWriterメソッドを実装したいのですか?

私はすでにプレーンJavaで/書き込み寄木細工のファイル見方についてこのSOWの質問に答えを与える:Write Parquet format to HDFS using Java API with out using Avro and MR

よろしく、

ロイック

関連する問題