2017-05-29 30 views
5
lihaoyi test$ tree 
. 
└── Foo.scala 

0 directories, 1 file 

lihaoyi test$ cat Foo.scala 
object Main{ 
    def main(args: Array[String]): Unit = { 
    println(getClass.getClassLoader.getResourceAsStream("java/lang/String.class")) 
    println(getClass.getClassLoader.getClass) 
    println(Thread.currentThread().getContextClassLoader.getResourceAsStream("java/lang/String.class")) 
    println(Thread.currentThread().getContextClassLoader.getClass) 
    } 
} 

lihaoyi test$ sbt run 
[info] Loading global plugins from /Users/lihaoyi/.sbt/0.13/plugins 
[info] Set current project to test (in build file:/Users/lihaoyi/Dropbox/Workspace/test/) 
[info] Updating {file:/Users/lihaoyi/Dropbox/Workspace/test/}test... 
[info] Resolving org.fusesource.jansi#jansi;1.4 ... 
[info] Done updating. 
[info] Compiling 1 Scala source to /Users/lihaoyi/Dropbox/Workspace/test/target/scala-2.10/classes... 
[info] Running Main 
[email protected]8ff2 
class sbt.classpath.ClasspathUtilities$$anon$1 
null 
class sbt.classpath.ClasspathFilter 
[success] Total time: 2 s, completed 29 May, 2017 4:14:11 PM 

lihaoyi test$ 

यहां, हम देख सकते हैं कि getClass.getClassLoader और Thread.currentThread.getContextClassLoader विभिन्न मान लौटा रहे हैं। और क्या है, Thread.currentThread.getContextClassLoaderjava/lang/String.class लोड करने से इंकार कर रहा है, जबकि दूसरा कर सकता है।क्यों एसबीटी के थ्रेड संदर्भ क्लासलोडर संसाधनों के रूप में जेडीके क्लासफाइल्स लोड नहीं कर सकते?

विशेष रूप से, जब मैं scalac/scala, या java की तरह एक बाहरी उपकरण का उपयोग कर जार फ़ाइल को चलाने, दोनों classloaders एक संसाधन

lihaoyi test$ scalac Foo.scala 

lihaoyi test$ scala Main 
[email protected]cdfa 
class scala.reflect.internal.util.ScalaClassLoader$URLClassLoader 
[email protected]724f 
class scala.reflect.internal.util.ScalaClassLoader$URLClassLoader 

मैं एसबीटी समान व्यवहार की उम्मीद करेंगे के रूप में classfile लोड करने में सक्षम हैं: Main.getClass.getClassLoader और Thread.currentThread().getContextClassLoader दोनों संसाधन के रूप में java/lang/String.class लोड करने में सक्षम होंगे। क्या देता है?

उत्तर

3

जेसन ज़ाग (पुनः नाम) के sbt launcher notes द्वारा प्रदान किए गए कुछ संकेत।

एसबीटी/लॉन्चर एक छोटा सा स्कैला एप्लिकेशन है जो एक मनमानी स्कैला प्रोग्राम (आमतौर पर, एसबीटी) को बूटस्ट्रैप्स को कॉन्फ़िगर करता है और एक आइवी निर्भरता संकल्प के माध्यम से सोर्स किया जाता है।

यह स्केल 2.10.6 युक्त एक बाल वर्गीकरण बनाता है। इसके एक बच्चे में एसबीटी स्वयं और xsbti/इंटरफ़ेस-0.13.11.jar शामिल है।

एसबीटी को स्केल कंपाइलर के लिए, या उपयोगकर्ता कोड के लिए प्लगइन कोड के लिए बाल वर्गीकरण बनाने के दौरान कक्षाओं को चुनने के लिए गैर-मानक क्लासलोडर प्रतिनिधिमंडल का उपयोग करने की आवश्यकता है।

एसबीटी में कुछ और संकेत 0.13 स्रोत:

def makeLoader(classpath: Seq[File], instance: ScalaInstance, nativeTemp: File): ClassLoader = 
    filterByClasspath(classpath, makeLoader(classpath, instance.loader, instance, nativeTemp)) 


def makeLoader(classpath: Seq[File], parent: ClassLoader, instance: ScalaInstance, nativeTemp: File): ClassLoader = 
    toLoader(classpath, parent, createClasspathResources(classpath, instance), nativeTemp) 

असल में एसबीटी कि एक मनमाना स्काला है एक जावा आवेदन की एक पानी के नल है संस्करण और आपका कोड, और आपके परीक्षण पुस्तकालयों के साथ ओरेकल/ओपनजेडीके के जावा पुस्तकालय के साथ ary। एक क्लासपाथ बनाने के लिए जो उन्हें बार-बार लोड किए बिना समझ में आता है, यह कुछ मानदंडों द्वारा फ़िल्टर किए गए क्लासलोडर्स का पदानुक्रम बना रहा है। (मुझे लगता है कि)

1

विशेष रूप से, इस समस्या के समाधान के लिए एक ही रास्ता है स्थापित करने के लिए

(fork in run) := true, 

(connectInput in run) := true, 
(outputStrategy in run) := Some(StdoutOutput), 

इस समस्या को हल करने लगता है यही कारण है, (Thread.currentThread().getContextClassLoader.getResourceAsStream("java/lang/String.class") अब काम करता है) है, लेकिन अन्य असंबंधित समस्याओं का परिचय (काँटेदार JVM कुछ समय लगता है बूट करने के लिए, ठंडा बूट करता है और गर्म करने में समय लगता है ...)

संबंधित मुद्दे

 संबंधित मुद्दे