Skip to content

Commit 7d5be56

Browse files
author
Samuele Pedronis
committed
Modified:
multi classloader support (I) * Proxies retrieve classes for return-type conversions from their classloaders. * BytecodeLoaders are setup with a set of referents and look for classes first through the sys.path loader and then through the loaders of the referents. makeup * Added specific SyspathJavaLoader loader class. * - python.options.extendedClassLoader
1 parent 97f1de5 commit 7d5be56

8 files changed

+211
-122
lines changed

org/python/compiler/ProxyMaker.java

+24-2
Original file line numberDiff line numberDiff line change
@@ -380,11 +380,33 @@ public void callMethod(Code code, String name, Class[] parameters,
380380
"org/python/core/PyObject", jcallName,
381381
"([Ljava/lang/Object;)Lorg/python/core/PyObject;");
382382
code.invokevirtual(jcall);
383-
383+
/* catching exceptions is not vm mandatory
384+
Label forname_start =code.getLabel();
385+
Label forname_end = code.getLabel();
386+
Label forname_exch_start = code.getLabel();
387+
Label forname_exch_end = code.getLabel();
388+
forname_start.setPosition();
389+
*/
390+
int forname = code.pool.Methodref(
391+
"java/lang/Class","forName",
392+
"(Ljava/lang/String;)Ljava/lang/Class;");
384393
code.ldc(ret.getName());
394+
code.invokestatic(forname);
395+
/*
396+
forname_end.setPosition();
397+
code.goto_(forname_exch_end);
398+
forname_exch_start.setPosition();
399+
code.stack = 1;
400+
code.pop(); // never reached, but this code keeps the verifier happy
401+
code.aconst_null();
402+
code.dup();
403+
forname_exch_end.setPosition();
404+
405+
code.addExceptionHandler(forname_start,forname_end,forname_exch_start,code.pool.Class("java/lang/ClassNotFoundException"));
406+
*/
385407
int tojava = code.pool.Methodref(
386408
"org/python/core/Py", "tojava",
387-
"(Lorg/python/core/PyObject;Ljava/lang/String;)Ljava/lang/Object;");
409+
"(Lorg/python/core/PyObject;Ljava/lang/Class;)Ljava/lang/Object;");
388410
code.invokestatic(tojava);
389411
// I guess I need this checkcast to keep the verifier happy
390412
code.checkcast(code.pool.Class(mapClass(ret)));

org/python/core/BytecodeLoader.java

+28-90
Original file line numberDiff line numberDiff line change
@@ -4,118 +4,56 @@
44
import java.io.*;
55
import java.util.StringTokenizer;
66
import java.util.Hashtable;
7+
import java.util.Vector;
78

89
public class BytecodeLoader extends ClassLoader
910
{
1011

11-
public InputStream getResourceAsStream(String res) {
12-
ClassLoader classLoader = Py.getSystemState().getClassLoader();
13-
if (classLoader != null) return classLoader.getResourceAsStream(res);
14-
15-
classLoader = this.getClass().getClassLoader();
16-
17-
InputStream ret;
18-
19-
if (classLoader != null) ret = classLoader.getResourceAsStream(res);
20-
else ret = ClassLoader.getSystemResourceAsStream(res);
21-
22-
if (ret != null) return ret;
23-
24-
if(res.charAt(0) == '/') res = res.substring(1);
25-
26-
res.replace('/',File.separatorChar);
27-
28-
PyList path = Py.getSystemState().path;
29-
for (int i=0; i < path.__len__(); i++) {
30-
String dir = path.get(i).__str__().toString();
31-
if (dir.length() == 0) dir = null;
32-
try {
33-
return new BufferedInputStream(new FileInputStream(new File(dir,res)));
34-
}
35-
catch (IOException e) {
36-
continue;
12+
private Vector parents;
13+
14+
public BytecodeLoader() {
15+
this(null);
16+
}
17+
18+
public BytecodeLoader(Vector referents) {
19+
parents = new Vector();
20+
21+
parents.addElement(imp.getSyspathJavaLoader());
22+
23+
if (referents != null) {
24+
for(int i = 0; i < referents.size(); i++) {
25+
try {
26+
ClassLoader cur = ((Class)referents.elementAt(i)).getClassLoader();
27+
if (cur != null && !parents.contains(cur)) {
28+
parents.addElement(cur);
29+
}
30+
} catch(SecurityException e) {
31+
}
3732
}
3833
}
39-
40-
return null;
34+
4135
}
4236

4337
// override from abstract base class
4438
protected Class loadClass(String name, boolean resolve)
4539
throws ClassNotFoundException
46-
{
47-
// System.err.println("loadClass("+name+", "+resolve+")");
48-
// First, if the Python runtime system has a default class loader,
49-
// defer to it.
50-
ClassLoader classLoader = Py.getSystemState().getClassLoader();
51-
if (classLoader != null)
52-
return classLoader.loadClass(name);
53-
// Search the sys.path for a .class file matching the named class.
54-
// TBD: This registry option is temporary.
55-
try {
56-
return Class.forName(name);
57-
}
58-
catch(ClassNotFoundException e) {
59-
}
60-
40+
{
6141
Class c = findLoadedClass(name);
6242
if (c != null)
6343
return c;
6444

65-
/* previously: if
66-
Options.extendedClassLoader &&
67-
// KLUDGE ALERT: without this test, running jpython
68-
// interactively from the build directory will fail with
69-
// ClassCircularityError or LinkageError. There's gotta be a
70-
// better way.
71-
!name.startsWith("org.python")
72-
*/
73-
{
74-
PyList path = Py.getSystemState().path;
75-
for (int i=0; i < path.__len__(); i++) {
76-
String dir = path.get(i).__str__().toString();
77-
FileInputStream fis = open(dir, name);
78-
if (fis == null)
79-
continue;
80-
try {
81-
int size = fis.available();
82-
byte[] buffer = new byte[size];
83-
fis.read(buffer);
84-
fis.close();
85-
return loadClassFromBytes(name, buffer);
86-
}
87-
catch (IOException e) {
88-
continue;
89-
}
45+
for (int i = 0; i < parents.size(); i++) {
46+
try {
47+
return ((ClassLoader)parents.elementAt(i)).loadClass(name);
48+
} catch(ClassNotFoundException e) {
9049
}
9150
}
51+
9252

9353
// couldn't find the .class file on sys.path
9454
throw new ClassNotFoundException(name);
9555
}
9656

97-
private FileInputStream open(String dir, String name) {
98-
String accum = "";
99-
boolean first = true;
100-
for (StringTokenizer t = new StringTokenizer(name, ".");
101-
t.hasMoreTokens();)
102-
{
103-
String token = t.nextToken();
104-
if (!first)
105-
accum += File.separator;
106-
accum += token;
107-
first = false;
108-
}
109-
try {
110-
if (dir.length() == 0)
111-
dir = null;
112-
return new FileInputStream(new File(dir, accum+".class"));
113-
}
114-
catch (FileNotFoundException e) {
115-
return null;
116-
}
117-
}
118-
11957
private Class loadClassFromBytes(String name, byte[] data) {
12058
// System.err.println("loadClassFromBytes("+name+", byte[])");
12159
Class c = defineClass(name, data, 0, data.length);

org/python/core/MakeProxies.java

+17-16
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,24 @@
1313

1414
class MakeProxies
1515
{
16-
private static Class makeClass(Class referent, String name,
16+
private static Class makeClass(Class referent, Vector secondary,String name,
1717
ByteArrayOutputStream bytes)
1818
{
19-
BytecodeLoader bcl;
20-
ClassLoader cl;
21-
// Use the superclass's class loader if it is a BytecodeLoader.
22-
// referent might be null if we're deriving from an interface. In
23-
// that case, this may or may not be the RTTD.
24-
if (referent != null &&
25-
(cl = referent.getClassLoader()) != null &&
26-
cl instanceof BytecodeLoader)
27-
{
28-
bcl = (BytecodeLoader)cl;
19+
Vector referents = null;
20+
21+
if (secondary != null) {
22+
if (referent != null) {
23+
secondary.insertElementAt(referent,0);
24+
referents = secondary;
25+
}
26+
} else {
27+
if (referent != null) {
28+
referents = new Vector();
29+
referents.addElement(referent);
30+
}
2931
}
30-
else
31-
bcl = imp.getSyspathJavaLoader();
32-
return bcl.makeClass(name, bytes.toByteArray());
32+
33+
return new BytecodeLoader(referents).makeClass(name, bytes.toByteArray());
3334
}
3435

3536
public static Class makeAdapter(Class c) {
@@ -44,7 +45,7 @@ public static Class makeAdapter(Class c) {
4445

4546
Py.saveClassFile(name, bytes);
4647

47-
Class pc = makeClass(c, name, bytes);
48+
Class pc = makeClass(c, null, name, bytes);
4849
return pc;
4950
}
5051

@@ -77,7 +78,7 @@ public static synchronized Class makeProxy(Class superclass,
7778
jm.classfile.write(bytes);
7879
Py.saveClassFile(proxyName, bytes);
7980

80-
return makeClass(superclass, jm.myClass, bytes);
81+
return makeClass(superclass, vinterfaces, jm.myClass, bytes);
8182
}
8283
catch (Exception exc) {
8384
throw Py.JavaError(exc);

org/python/core/Options.java

+3-5
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,13 @@ public class Options
3535
// accessible flag on the member.
3636
public static boolean respectJavaAccessibility = true;
3737

38+
/* no longer necessary
3839
// Allow JPython's classloader to find and load .class files on
3940
// sys.path. This only happens for anonymous inner classes, but may
4041
// have unintended side-effects. This option is temporary.
4142
public static boolean extendedClassLoader = true;
42-
43+
*/
44+
4345
// TBD
4446
public static boolean importSite = true;
4547

@@ -102,10 +104,6 @@ public static void setFromRegistry() {
102104
getBooleanOption("security.respectJavaAccessibility",
103105
Options.respectJavaAccessibility);
104106

105-
Options.extendedClassLoader =
106-
getBooleanOption("options.extendedClassLoader",
107-
Options.extendedClassLoader);
108-
109107
Options.proxyDebugDirectory =
110108
getStringOption("options.proxyDebugDirectory",
111109
Options.proxyDebugDirectory);

org/python/core/PySystemState.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ public PySystemState() {
164164
__stdin__ = stdin = new PyFile(getSystemIn(), "<stdin>");
165165

166166
// This isn't quite right...
167-
builtins = PyJavaClass.lookup(__builtin__.class).__dict__;
167+
builtins = PyJavaClass.lookup(__builtin__.class).__getattr__("__dict__");
168168
PyModule __builtin__ = new PyModule("__builtin__", builtins);
169169
modules.__setitem__("__builtin__", __builtin__);
170170

0 commit comments

Comments
 (0)