2005-02-13 Paul Boddie Attempted to simplify the class loading mechanism by adding instance-level state to remember which classes have been imported so far. Only at the top level will such classes be created and initialised. Added a convenience method to ClassTranslator.
     1 <?xml version="1.0" encoding="iso-8859-1"?>     2 <html xmlns="">     3 <head>     4   <title>javaclass/ClassFile</title>     5   <meta name="generator" content="amaya 8.1a, see" />     6   <link xmlns:xlink="" href="styles.css"     7   rel="stylesheet" type="text/css" />     8 </head>     9     10 <body>    11 <h1>javaclass</h1>    12     13 <p>The javaclass collection of packages and utilities (also known as    14 ClassFile) provides a means of importing Java classes and packages directly    15 into Python, without the need for a Java virtual machine, so that the classes    16 may be instantiated, accessed, run and manipulated just like Python classes,    17 and that the resulting objects and methods can be accessed and manipulated    18 just like Python objects and methods. It should be possible to run compiled    19 Java programs with the Python interpreter and not notice that it isn't the    20 Java virtual machine being used - given sufficient library support for the    21 program concerned, of course.</p>    22     23 <h2>Quick Examples</h2>    24     25 <p>It can be quicker to see what this is about by seeing some examples.</p>    26     27 <h3>The Not Very Convincing Example</h3>    28     29 <p>You can run Java classes by finding one with a main method and executing    30 it. Here's a comparison of a freshly prepared Java class being run in Python    31 and in a Java virtual machine respectively:</p>    32 <pre class="Prompt">cd tests/</pre>    33 <pre class="Prompt">javac</pre>    34 <pre class="PromptRequest"> Value</pre>    35 <pre class="PromptResponse">v.getValue() correct: 123    36 v.getValue() correct: 456    37 v.isPositive() correct: 1    38 v.isPositive() correct: 0    39 correct: -1    40 correct: 1    41 correct: 0    42 v.getValue() == v2.getValue() correct: 0    43 v2.add(-123) correct: 0    44 v2.getValue() correct: 255</pre>    45 <pre class="PromptRequest">java Value</pre>    46 <pre class="PromptResponse">v.getValue() correct: 123    47 v.getValue() correct: 456    48 v.isPositive() correct: true    49 v.isPositive() correct: false    50 correct: -1    51 correct: 1    52 correct: 0    53 v.getValue() == v2.getValue() correct: false    54 v2.add(-123) correct: 0    55 v2.getValue() correct: 255</pre>    56     57 <h3>The Slightly More Credible Example</h3>    58     59 <p>It can be more interesting to get into Python's interactive mode and then    60 start playing around with Java classes:</p>    61 <pre class="PromptResponse">Python 2.2.2 (#2, Jan 21 2005, 16:16:57)    62 [GCC 2.96 20000731 (Red Hat Linux 7.3 2.96-112)] on linux2    63 Type "help", "copyright", "credits" or "license" for more information.</pre>    64 <pre class="PythonPrompt">import javaclass.classhook</pre>    65 <pre class="PythonPrompt">from __this__ import Value</pre>    66 <pre class="PythonPrompt">dir()</pre>    67 <pre class="PromptResponse">['Value', '__builtins__', '__doc__', '__name__',    68 'javaclass']</pre>    69 <pre class="PythonPrompt">dir(Value)</pre>    70 <pre class="PromptResponse">['__class__', '__delattr__', '__dict__', '__doc__',    71 '__getattribute__', '__hash__', '__init__', '__init______I_', '__module__',    72 '__new__', '__reduce__', '__repr__', '__setattr__', '__str__', '__weakref__',    73 'add', 'add____I_', 'compare', 'compare____I_', 'getClass', 'getClass___',    74 'getValue', 'getValue___', 'isPositive', 'isPositive___', 'main',    75 'main___java__lang__String_array_', 'newValue', 'newValue___', 'setValue',    76 'setValue____I_']</pre>    77 <pre class="PythonPrompt">v = Value(20050121)</pre>    78 <pre class="PythonPrompt">v.getValue()</pre>    79 <pre class="PromptResponse">20050121</pre>    80 <pre class="PythonPrompt">v.setValue(20050401)</pre>    81 <pre class="PythonPrompt">v.getValue()</pre>    82 <pre class="PromptResponse">20050401</pre>    83     84 <h2>Copyright and Licence</h2>    85     86 <p>The javaclass software is distributed under the terms of the GNU Lesser    87 General Public Licence (LGPL). See the file <code>COPYING.txt</code> in the    88 <code>docs</code> directory within the source code distribution.</p>    89     90 <h2>Getting Started</h2>    91     92 <p>See the <code>README.txt</code> file in the distribution directory.</p>    93     94 <h2>Motivation</h2>    95     96 <p>Pick one of the following:</p>    97 <ul>    98   <li>The need/desire to access Java libraries from Python without firing up    99     Java virtual machines or switching to Jython (and thereby losing   100     convenient access to various CPython libraries).</li>   101   <li>Mixing languages available for the Java runtime with Python.</li>   102   <li>Static typing for the Python environment, albeit achieved by writing   103     Java or other appropriate languages.</li>   104   <li>Having an open source environment from top to bottom to run Java   105     bytecode on.</li>   106   <li>Experimentation around import hooks, bytecode generation; observation   107     of different runtime and type systems interacting.</li>   108   <li>Making Python libraries available to Java programs - Tkinter for Java,   109     anyone?!</li>   110 </ul>   111    112 <h2>Limitations</h2>   113    114 <p>It isn't all great, however. Here are some reasons why this might not do   115 what you want it to:</p>   116 <ul>   117   <li>It runs on the Python runtime which does not have the security,   118     threading and just-in-time compiler features that people enjoy about Java   119     runtimes, so if what you like to do is to run one big servlet container   120     with lots of classes and threads from different people floating around,   121     this isn't going to protect them from doing all sorts of things to each   122     other and to your system. However, you may take the unfashionable view   123     that the operating system is supposed to do that kind of thing.</li>   124   <li>It works by generating Python bytecode from the Java bytecode in class   125     files (and .jar archives). Generally, anyone who is anyone in the Python   126     pantheon has largely recommended against doing anything with the   127     bytecode, despite noble efforts to make exciting things happen by   128     transforming it, optimising it, and so on. (Instead, there's been more   129     emphasis on lots of runtime baggage for things which could be done by   130     analysis of the code with modified bytecode being produced as a result,   131     and let's not get started on some of the syntax enhancements!)   132     Consequently, stability might be an issue for some configurations,   133     especially since CPython doesn't fail particularly graciously with badly   134     behaved bytecode.</li>   135   <li>Some of the translation from Java to Python bytecode takes a few   136     liberties. For example, Java exceptions are handled in ways reminiscent   137     of a 1980s microcomputer assembly language, whereas Python bytecode has   138     higher level constructs for exceptions; this translation can probably be   139     done incorrectly, triggering some kind of bytecode misbehaviour, and we   140     all know what happens then.</li>   141   <li>At the Python level, not all things seem totally right. For example,   142     Java bytecode instructions are used to instantiate and then initialise   143     exceptions just like other objects, and while Python can support this   144     with new-style objects, Python won't let you use new-style objects as   145     exceptions. Consequently, when Java exceptions appear in Python programs,   146     they will be wrapped in old-style exceptions and have to be handled   147     specially.</li>   148   <li>In order to support method dispatch properly, special names are used   149     for the translated methods which include the type information found in   150     the bytecode; things like <code>main___java__lang__String_array_</code>   151     and <code>setValue____I_</code> appear when you look inside classes and   152     objects. When implementing libraries in Python for Java programs, such   153     method naming conventions have to be used because the original code is   154     very specific about which method is being invoked, and for specialised   155     versions of <code>__init__</code> it becomes necessary to do a   156     <code>setattr</code> to add such methods into classes because of various   157     "name mangling" measures in the Python compilation process. Now, many   158     people might start advocating decorators at this point, but not everyone   159     is running the very latest stuff from, and decorators won't   160     help you target a specific specialised method anyway.</li>   161   <li>Special dispatcher methods are often generated for the benefit of   162     Python access to Java classes, even though such methods are not strictly   163     necessary for the Java classes to work amongst themselves. Such methods   164     are only generated when many methods of the same name reside in a given   165     class, since where Java distinguishes between them on the basis of the   166     signatures, Python permits only one method of a given name and needs   167     additional logic to dispatch to the actual method implementations on the   168     basis of the types of the incoming values. The implementation of the   169     dispatcher method is naive and does not try to order the type checks and   170     dispatches according to the specificity of the parameter types; thus, a   171     more reliable but more verbose way of ensuring that the correct method in   172     such cases is called from a Python program may be to use the special long   173     method name (eg. <code>setValue____I_</code>).</li>   174   <li>Imported and translated bytecode is not written out or cached. This   175     means that a fair amount of work happens every time you need to import   176     Java classes, although the generation of .pyc files could be introduced   177     provided that it captured the slightly different import semantics of   178     Java; for example, you can import classes belonging to a package from   179     several places on the PYTHONPATH, and this is something that generally   180     isn't allowed/supported with the classic Python module import   181   mechanisms.</li>   182   <li>Most Java programs need standard Java library (also known as the Java   183     API) classes; indeed, with <code>java.lang.String</code> and seemingly   184     <code>java.lang.StringBuffer</code> required just for the usage of   185     strings, and with the classic <code>main</code> method having   186     <code>String[]</code> in its signature, some kind of library   187     implementation is obviously necessary. Whilst importing everything from   188     the .jar files bundled with Sun's JRE might be tempting, there may be a   189     certain amount of native calling going on in secret which would defeat   190     this approach, and anyone seriously interested in running Java code in   191     Python should really want to steer clear of such proprietary dependencies   192     anyway. It could be possible to wrap and make use of GNU Classpath or   193     some other open source Java API implementation, but the cleanest (but not   194     necessarily the least time-consuming) approach is surely to implement the   195     standard API classes in Python, and a package called <code>java</code> is   196     included which contains some fairly quick and dirty implementations to   197     get things working.</li>   198 </ul>   199    200 <h2>Suggestions for Python Improvements</h2>   201 <ul>   202   <li>Make the bytecode interpreter more robust when encountering badly   203     behaved bytecode, consider bytecode verification and other exciting   204     features.</li>   205   <li>Allow new-style objects as exceptions. Actually, just do something   206     about the whole old-style vs. new-style class thing!</li>   207   <li>Allow possible optimisation for things like statically predetermined   208     method calls. The debate about static typing intersects slightly with the   209     need to define methods with parameters of particular types, but   210     supporting Java-style method "coexistence" (or multimethods, or whatever   211     the proper name is) would presumably involve doing lots of things to the   212     language that were once thought to be highly un-Pythonic. Besides, the   213     need to interoperate with statically typed languages shouldn't dictate   214     the design of Python, especially if better type systems could be adopted   215     instead, leaving the static typing glue for strictly special   216   occasions.</li>   217   <li>Not that threaded Java programs have been run on Python yet, but with   218     Python's current threading architecture I'd expect some   219   disappointment.</li>   220 </ul>   221 </body>   222 </html>