Thanks!
With your example I begin a little bit to understand how the
classloader works.
And I didn't know about ScalaClassLoader.
The basic ingredients of the recipe are:
1. Create a custom classloader . Override the findClass method in the
custom classloader with the custom implementation.
2. Instantiate this custom classloader and associate a folder (e.g.
"hidden" with an on call site created classloader (e.g.
getClass.getClassLoader). Somehow the current folder "." doesn't work.
3. Use a proxy class (e.g. classload.Testee) to call the real target
class (e.g. loadclass.Foo). The proxy and target must reside in a
package (e.g. loadclass). Somehow packageless and directly calling the
target class doesn't work.
4. The proxy and the target class has to be moved in the classloader
associated folder (that is "hidden")
5. Then you can call loadclass which in turn calls custom classloader
findClass
main.scala
==========
package loadclass
import tools.nsc.util.ScalaClassLoader
import java.io._
class Foo { def m() = "M"}
class Testee {
def test() =
println(getClass.getClassLoader.loadClass("loadclass.Foo").newInstance.asInstanceOf[Foo].m)
}
class FileClassLoader(f: File, p: ClassLoader) extends ClassLoader(p)
with ScalaClassLoader {
override protected def trace: Boolean = true
override def findClass(name: String) = {
val b = loadClassData(name)
val cls = defineClass(name, b, 0, b.length)
cls
}
def hex(buf: Array[Byte]): String = buf.map("%02x" format
_).mkString
def loadClassData(name: String): Array[Byte] = {
val what = new File(f, name.replace('.','/') + ".class")
if (!what.exists) throw new ClassNotFoundException(name)
val is = new java.io.FileInputStream(what)
val bis = new java.io.BufferedInputStream(is)
val b = Stream.continually(bis.read).takeWhile(-1 !
=).map(_.toByte).toArray
println(b.length)
println(hex(b))
b
}
}
object Main {
def main(args: Array[String]) {
val clsloader = new FileClassLoader(new
File("hidden"),getClass.getClassLoader)
val cls = clsloader.loadClass("loadclass.Testee")
val sut = cls.newInstance
cls.getDeclaredMethod("test").invoke(sut)
}
}
C:\scala-2.10.0-M2\footest>scala loadclass.Main
1022
cafebabe00000031003b01000a536f7572636546696c6501000a6d61696e2e7363616c6101000474
657374010003282956010004436f646501000d7363616c612f507265646566240700060100074d4f
44554c452401000f4c7363616c612f507265646566243b0c00080009090007000a01000f4c696e65
4e756d6265725461626c650100106a6176612f6c616e672f4f626a65637407000d01000867657443
6c61737301001328294c6a6176612f6c616e672f436c6173733b0c000f00100a000e001101000f6a
6176612f6c616e672f436c61737307001301000e676574436c6173734c6f6164657201001928294c
6a6176612f6c616e672f436c6173734c6f616465723b0c001500160a0014001701000d6c6f616463
6c6173732e466f6f0800190100156a6176612f6c616e672f436c6173734c6f6164657207001b0100
096c6f6164436c617373010025284c6a6176612f6c616e672f537472696e673b294c6a6176612f6c
616e672f436c6173733b0c001d001e0a001c001f01000b6e6577496e7374616e636501001428294c
6a6176612f6c616e672f4f626a6563743b0c002100220a0014002301000d6c6f6164636c6173732f
466f6f0700250100016d01001428294c6a6176612f6c616e672f537472696e673b0c002700280a00
2600290100077072696e746c6e010015284c6a6176612f6c616e672f4f626a6563743b29560c002b
002c0a0007002d0100063c696e69743e0c002f00040a000e00300100085363616c6153696701001e
4c7363616c612f7265666c6563742f5363616c615369676e61747572653b01000562797465730100
bd06017d3141210102010b0931412b5a3a754b1654116141010a593e0c476d193762674e1c016145
02010d3901226102070e032151212103060209310c676e1a0602170521212e193c62130969014201
0450452a2c370d1e09031f49691101050602230529316f59316d432611310305020c270e0c472e59
286355161c470f430316011105612301043d533a4c474f100b022f41110104410702052129210401
4301370521412f5a3a75290561024341081e13097102430103565d26240801001952756e74696d65
56697369626c65416e6e6f746174696f6e730100106c6f6164636c6173732f546573746565070037
0100117363616c612f5363616c614f626a65637407003900210038000e0001003a00000002000100
0300040001000500000034000300010000001cb2000b2ab60012b60018121ab60020b60024c00026
b6002ab6002eb100000001000c000000060001000000080001002f0004000100050000001d000100
01000000052ab70031b100000001000c000000060001000000070003000100000002000200320000
000305000000360000000b0001003300010034730035
[Cl#17933220] loadClass(scala.ScalaObject, false) = interface
scala.ScalaObject
[Cl#17933220] loadClass(java.lang.Object, false) = class
java.lang.Object
[Cl#17933220] loadClass(loadclass.Testee, false) = class
loadclass.Testee
[Cl#17933220] loadClass(scala.Predef$, false) = class scala.Predef$
[Cl#17933220] loadClass(java.lang.Class, false) = class
java.lang.Class
[Cl#17933220] loadClass(java.lang.ClassLoader, false) = class
java.lang.ClassLoa
der
585
cafebabe00000031001801000a536f7572636546696c6501000a6d61696e2e7363616c610100016d
01001428294c6a6176612f6c616e672f537472696e673b010004436f64650100014d08000601000f
4c696e654e756d6265725461626c650100063c696e69743e0100032829560100106a6176612f6c61
6e672f4f626a65637407000b0c0009000a0a000c000d0100085363616c6153696701001e4c736361
6c612f7265666c6563742f5363616c615369676e61747572653b01000562797465730100b806017d
3141210102010b091961695c380b030d0911025c3862490e64176d5d3a04014d190141020811051d
61512201050b05255111010237625d1e541161430105550634182d03020e110931714a1936664752
042261040a0e0341511121450106670e0c472e590503274111316255326259067c254d5b33646922
2951030143012d053141281b386a697a221261060903310169114101050635012109614701025b52
0941040502083b25116104030207275214184e5c3401001952756e74696d6556697369626c65416e
6e6f746174696f6e7301000d6c6f6164636c6173732f466f6f0700140100117363616c612f536361
6c614f626a65637407001600210015000c0001001700000002000100030004000100050000001b00
010001000000031207b00000000100080000000600010000000500010009000a000100050000001d
00010001000000052ab7000eb1000000010008000000060001000000050003000100000002000200
0f0000000305000000130000000b0001001000010011730012
[Cl#17933220] loadClass(loadclass.Foo, false) = class loadclass.Foo
M
On 19 apr, 02:11, Som Snytt <
som.sn...@gmail.com> wrote:
> On Wed, Apr 18, 2012 at 5:51 AM, Dave <
dave.mahabiers...@hotmail.com> wrote:
> > No it is not working
>
> Sorry I misled you; it was my midnight bungle; that was an intermediate
> result that was wrong.
>
> As penance, here is what I wound up with. As you can see, ScalaClassLoader
> is not magical, qua classloader, but it (SCL) is instructive in other
> ways. To recap, this test gets Foo loaded once by your FileClassLoader.
> As you pointed out, your custom findClass is called (only) if the
> parent.loadClass comes up empty.
>
> usage: scalac loadclass.scala ; mv loadclass/Foo.class
> loadclass/Testee.class hidden/loadclass ; scala loadclass.Test
>
> package loadclass
>
> // put me in "hidden"
> class Foo { def m() = "M"}
>
> // put me in "hidden"
> class Testee {
> def test() =
> println(getClass.getClassLoader.loadClass("loadclass.Foo").newInstance.asInstanceOf[Foo].m)