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