开发者社区 问答 正文

Java语言编写的用于Avro工具的Scala类加载器运行方法

我在确定加载“ Avro Tools”类及其run方法的方法时遇到了一些困难。问题出在Java和Scala接口与类加载方法之间。由于avro在Spark应用程序的其他位置使用了不同版本来加载数据文件,因此我需要能够将此特定方法视为对另一版本avro-tools的孤立调用。

以下是我的代码: package samples

import java.io.{ByteArrayOutputStream, InputStream} import org.junit.runner.RunWith import org.specs2.mutable._ import org.specs2.runner._

import scala.collection.JavaConverters._

@RunWith(classOf[JUnitRunner]) class MySpecTest extends Specification { "Class Loader" should { "load an implement a class" in {

  var classLoader = new java.net.URLClassLoader(
    Array(new java.io.File("./avro-tools-1.9.1.jar").toURI.toURL),
    this.getClass.getClassLoader)

  var clazzDFRT = classLoader.loadClass("org.apache.avro.tool.DataFileRepairTool")

  val objDFRT = clazzDFRT.getConstructor().newInstance()
  val toolCmdArgsAsJava = List("-o", "all", "questionable.avro", "fixed.avro").asJava
  val stdin : InputStream = null
  val out: ByteArrayOutputStream = new ByteArrayOutputStream
  val err = System.err
  val toolClassArgsAsJava = List(stdin, out,err, toolCmdArgsAsJava).asJava

  //  parameterTypes: Class[_] *
  //  public int run( InputStream stdin, PrintStream out, PrintStream err, List<String> args)
  val method = clazzDFRT.getMethod("run",  Class[_] : _*)

  method.invoke(objDFRT.asInstanceOf[Object], toolClassArgsAsJava)

  // sidebar: is this the end result for the Unit test - want out str with summary
  out.toString("UTF-8").contains("File Summary")
}

} } 我在getMethod部分似乎有一些问题,但也许整个解决方案都有些不足-我需要能够调用该方法以及进行加载,实例化或...

如何解决此问题以运行整个代码段(并修复损坏的avro)?

展开
收起
被纵养的懒猫 2019-09-30 14:57:13 509 分享
分享
版权
举报
阿里云 AI 助理回答

你的代码片段中尝试动态加载特定版本的Avro Tools jar并调用其中的方法来修复损坏的Avro文件,这在概念上是正确的。不过,你遇到的问题可能与方法签名的解析有关。getMethod需要精确匹配方法的名称和参数类型。对于org.apache.avro.tool.DataFileRepairTool#run方法,其签名期望的是(InputStream, PrintStream, PrintStream, List<String>)

这里是一个修改后的代码段,更正了getMethod调用的部分:

package samples

import java.io.{ByteArrayOutputStream, InputStream}
import org.junit.runner.RunWith
import org.specs2.mutable._
import org.specs2.runner._
import scala.collection.JavaConverters._
import java.lang.reflect.Method

@RunWith(classOf[JUnitRunner])
class MySpecTest extends Specification {
  "Class Loader" should {
    "load an implement a class" in {
      val classLoader = new java.net.URLClassLoader(
        Array(new java.io.File("./avro-tools-1.9.1.jar").toURI.toURL),
        this.getClass.getClassLoader)

      val clazzDFRT = classLoader.loadClass("org.apache.avro.tool.DataFileRepairTool")
      val objDFRT = clazzDFRT.getConstructor().newInstance()

      // Correct parameter types for the run method
      val inputStreamClass = classOf[InputStream]
      val printStreamClass = classOf[java.io.PrintStream]
      val stringListClass = classOf[java.util.List[_]].asInstanceOf[Class[java.util.List[String]]]

      val toolCmdArgsAsJava = List("-o", "all", "questionable.avro", "fixed.avro").asJava
      val stdin: InputStream = null
      val out: ByteArrayOutputStream = new ByteArrayOutputStream
      val err = System.err
      
      // Get the run method with correct parameters
      val method = clazzDFRT.getMethod("run", inputStreamClass, printStreamClass, printStreamClass, stringListClass)

      // Invoke the run method
      method.invoke(objDFRT, stdin, out, err, toolCmdArgsAsJava)

      // Check the output
      out.toString("UTF-8").contains("File Summary") must beTrue
    }
  }
}

主要更改包括: 1. 明确指定getMethod中的参数类型,确保它们与DataFileRepairTool#run方法的实际签名相匹配。 2. 使用asInstanceOf[Class[java.util.List[String]]]来正确地表示第四个参数的类型为字符串列表。 3. 添加了一个断言检查输出是否包含预期的摘要信息,以完成单元测试逻辑。

请确保你的项目依赖管理正确无误,且./avro-tools-1.9.1.jar路径是正确的,并且该jar确实包含了你想要调用的类和方法。此外,由于Scala和Java的交互,注意反射调用可能存在的类型不匹配问题。

有帮助
无帮助
AI 助理回答生成答案可能存在不准确,仅供参考
0 条回答
写回答
取消 提交回答
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等