如何在不遇到SecurityException的情况下从Scala脚本引用java.sql?

Wil*_*son 5 java scala jdbc sbt java-9

从Java 9开始,直接从scala脚本使用时,从Scala中调用java.sql中定义的对象会抛出java.lang.SecurityException.

Java Version: 10.0.1
Scala Version: 2.12.4
sbt Version: 1.2.0
Run Code Online (Sandbox Code Playgroud)

下面的屏幕截图是一个完整的最小工作示例,其中包含适用于工作和非工作版本的控制台输出.具体来说:将脚本代码复制到类中,并从该类运行它,可以解决问题.有没有办法编写直接使用对象的Scala脚本java.sql

build.sbt

name := "mypackage"
version := "0.1"
scalaVersion := "2.12.4"

libraryDependencies += "org.postgresql" % "postgresql" % "42.2.4"
Run Code Online (Sandbox Code Playgroud)

broken-script.scala

import java.sql.{Connection, DriverManager}
import java.util.Properties

object Main {

  private def url = "jdbc:postgresql://localhost:5432/postgres"

  val credentials: Properties ={
    val properties = new Properties()
    properties.setProperty("user", "integration_test")
    properties.setProperty("password", "integration-pass")

    properties
  }

  def connect(): Connection =
    DriverManager.getConnection(url, credentials)


  def run(): Unit = {
    connect()
  }

}

Main.run()
Run Code Online (Sandbox Code Playgroud)

如下面的控制台输出所示,broken-script.scala遇到SecurityException.

brokenScript.scala Output

:load scripts/broken-script.scala
Loading scripts/broken-script.scala...
import java.sql.{Connection, DriverManager}
import java.util.Properties
defined object Main
java.lang.securityException: Prohibited package name: java.sql
  at java.base/java/lang.ClassLoader.preDefineClass(ClassLoader.java:891)
  at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java 1007)
  at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
  at java.base/java.net.URLClassLoader.defineClass(URLClassLoader.java:545)
  at java.base/java.net.URLClassLoader.access$100(URLClassLoader.java:83)
  at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:453)
  at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:447)
  at java.base/java.security.AccessController.doPrivileged(Native Method)
  at java.base/net.URLClassLoader.findClass(URLClassLoader.java:446)
  at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:566)
  at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:553)
  at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:499)
  at Main$.connect(scripts/broken-script.scala:26)
  at Main$.run(scripts/broken-script.scala:30)
Run Code Online (Sandbox Code Playgroud)

src/main/scala/mypackage/Main.scala

package mypackage

import java.sql.{Connection, DriverManager}
import java.util.Properties

object Main {

  private def url = "jdbc:postgresql://localhost:5432/postgres"

  val credentials: Properties ={
    val properties = new Properties()
    properties.setProperty("user", "integration_test")
    properties.setProperty("password", "integration-pass")

    properties
  }

  def connect(): Connection =
    DriverManager.getConnection(url, credentials)


  def run(): Unit = {
    connect()
  }

}
Run Code Online (Sandbox Code Playgroud)

working-script.scala

mypackage.Main.run()

println("Success")
Run Code Online (Sandbox Code Playgroud)

整个项目的图像.

在此输入图像描述

the*_*Man 2

编辑:请参阅稍后有关类加载器的评论。


我自己从来没有引用过 java.sql ,所以这不是来自个人经验,但它看起来与这个问题相同:java.lang.SecurityException: errorwhenexecutingoutsideEclipse,其中问题仅发生在外部IDE。看起来您没有自己的以“java”开头的类或包,所以事实并非如此。你的类路径是什么样的?这是 IDE 构建依赖项的方式的问题,因此我认为需要在 Intellij 中进行操作,而不是更改脚本 - 像这样:How to build JARs from Intellijproperly