Java-Gaming.org Hi !
Featured games (81)
games approved by the League of Dukes
Games in Showcase (513)
Games in Android Showcase (119)
games submitted by our members
Games in WIP (576)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Custom ClassLoader example to allow two Singletons  (Read 3535 times)
0 Members and 2 Guests are viewing this topic.
Offline leknor

Junior Duke




ROCK!!!


« Posted 2003-01-31 12:02:41 »

For another thread I created an example ClassLoader to demonstrate how you can have two different instances of a static field running in the same JVM. There is a zip file with code at: http://flick.nerdc.ufl.edu/jgo/ClassLoaderNamespaces.zip but incase the server is offline I'll include the code below.

File: /game/foo/Bar.java
1  
2  
3  
4  
5  
6  
7  
8  
9  
package foo;

public class Bar {
    private static int count = 0;

    public String toString() {
        return String.valueOf(++count);
    }
}


File: /loader/Test.java
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
import java.io.File;

public class Test {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        String myPackage = "foo.";
        String baseDir = ".." + File.separator + "game" + File.separator; // ../game/ on UNIX or ..\game\ on DOS

        // Create two ClassLoaders so we have two different namespaces
        ClassLoader cl1 = new SimpleClassLoader(myPackage, baseDir);
        ClassLoader cl2 = new SimpleClassLoader(myPackage, baseDir);

        // Create three Objects, two of which share the same ClassLoader
        Object o1 = cl1.loadClass("foo.Bar").newInstance();
        Object o2 = cl2.loadClass("foo.Bar").newInstance();
        Object o3 = cl1.loadClass("foo.Bar").newInstance(); // Same ClassLoader as o1

        // Print the output
        System.out.println("o1: " + o1.toString());
        System.out.println("o2: " + o2.toString());
        System.out.println("=======");
        System.out.println("o1: " + o1.toString());
        System.out.println("o2: " + o2.toString());
        System.out.println("=======");
        System.out.println("o1: " + o1.toString());
        System.out.println("o2: " + o2.toString());
        System.out.println("=======");
        System.out.println("o1: " + o1.toString());
        System.out.println("o2: " + o2.toString());
        System.out.println("o3: " + o3.toString());
        System.out.println("=======");
        System.out.println("o1: " + o1.toString());
        System.out.println("o2: " + o2.toString()); // Will be different than o1 because of o3 above
        System.out.println("o3: " + o3.toString());
        System.out.println("=======");
        System.out.println("o1: " + o1.toString());
        System.out.println("o2: " + o2.toString());
        System.out.println("o3: " + o3.toString());
    }
}


File: /loader/SimpleClassLoader.java which is based on: http://www.javaworld.com/javaworld/jw-10-1996/indepth/indepth.src.html
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
120  
121  
122  
123  
124  
125  
126  
127  
128  
129  
130  
131  
132  
/*
 * SimpleClassLoader.java - a bare bones class loader.
 *
 * Copyright (c) 1996 Chuck McManis, All Rights Reserved.
 *
 * Permission to use, copy, modify, and distribute this software
 * and its documentation for NON-COMMERCIAL purposes and without
 * fee is hereby granted provided that this copyright notice
 * appears in all copies.
 *
 * CHUCK MCMANIS MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE
 * SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING
 * BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. CHUCK MCMANIS
 * SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT
 * OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
 */


// EDIT: Whatever was here before was a mess
import java.io.FileInputStream;
import java.io.File;
import java.util.Hashtable;

public class SimpleClassLoader extends ClassLoader {
    private Hashtable classes = new Hashtable();

    // NEW
    private String myPackage;
    private String codeBase;

    public SimpleClassLoader(String myPackage, String codeBase) {
        // NEW
        this.myPackage = myPackage;
        this.codeBase = codeBase;
    }

    /**
     * This sample function for reading class implementations reads
     * them from the local file system
     */

    private byte getClassImplFromDataBase(String className)[] {
        System.err.println("        >>>>>> Fetching the implementation of " + className);
        byte result[];


        // NEW: convert package seperators '.' to directory seperators
        StringBuffer sb = new StringBuffer(className);
        for (int i=0, n=sb.length(); i < n; i++) {
            if (sb.charAt(i) == '.') {
                sb.setCharAt(i, File.separatorChar);
            }
        }
        className = sb.append(".class").toString();
        System.err.println("New className: " + className); // to double check

        try {
            // EDIT: Moved some stuff up a few lines
            // FileInputStream fi = new FileInputStream("store\\"+className+".impl");
            FileInputStream fi = new FileInputStream(codeBase + className);
            result = new byte[fi.available()];
            fi.read(result);
            return result;
        } catch (Exception e) {

            /*
             * If we caught an exception, either the class wasnt found or it
             * was unreadable by our process.
             */

            return null;
        }
    }

    /**
     * This is a simple version for external clients since they
     * will always want the class resolved before it is returned
     * to them.
     */

    public Class loadClass(String className) throws ClassNotFoundException {
        return (loadClass(className, true));
    }

    /**
     * This is the required version of loadClass which is called
     * both from loadClass above and from the internal function
     * FindClassFromClass.
     */

    public synchronized Class loadClass(String className, boolean resolveIt) throws ClassNotFoundException {
        Class result;
        byte classData[];

        System.err.println("        >>>>>> Load class : " + className);

        /* Check our local cache of classes */
        result = (Class)classes.get(className);
        if (result != null) {
            System.err.println("        >>>>>> returning cached result.");
            return result;
        }

        // NEW: Added the if startsWith
        if (!className.startsWith(myPackage)) {
            /* Check with the primordial class loader */
            try {
                result = super.findSystemClass(className);
                System.err.println("        >>>>>> returning system class (in CLASSPATH).");
                return result;
            } catch (ClassNotFoundException e) {
                System.err.println("        >>>>>> Not a system class.");
            }
        }

        /* Try to load it from our repository */
        classData = getClassImplFromDataBase(className);
        if (classData == null) {
            throw new ClassNotFoundException();
        }

        /* Define it (parse the class file) */
        result = defineClass(classData, 0, classData.length);
        if (result == null) {
            throw new ClassFormatError();
        }

        if (resolveIt) {
            resolveClass(result);
        }

        classes.put(className, result);
        System.err.println("        >>>>>> Returning newly loaded class.");
        return result;
    }
}


And when you run `java Test` you get output something like:
Quote
o1: 1
o2: 1
=======
o1: 2
o2: 2
=======
o1: 3
o2: 3
=======
o1: 4
o2: 4
o3: 5
=======
o1: 6
o2: 5
o3: 7
=======
o1: 8
o2: 6
o3: 9


Hope this is useful.
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

Longarmx (35 views)
2014-10-17 03:59:02

Norakomi (27 views)
2014-10-16 15:22:06

Norakomi (24 views)
2014-10-16 15:20:20

lcass (27 views)
2014-10-15 16:18:58

TehJavaDev (52 views)
2014-10-14 00:39:48

TehJavaDev (54 views)
2014-10-14 00:35:47

TehJavaDev (42 views)
2014-10-14 00:32:37

BurntPizza (63 views)
2014-10-11 23:24:42

BurntPizza (36 views)
2014-10-11 23:10:45

BurntPizza (76 views)
2014-10-11 22:30:10
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!