|
| 1 | +# About Jython Compatibility |
| 2 | + |
| 3 | +Full Jython compatibility is not a goal of this project. One major reason for |
| 4 | +this is that most Jython code that uses Java integration will be based on a |
| 5 | +stable Jython release, and these only come in Python 2.x versions. The GraalVM |
| 6 | +implementation of Python, in contrast, is only targeting Python 3.x. |
| 7 | + |
| 8 | +Nonetheless, there are certain features of Jython's Java integration that we can |
| 9 | +offer similarly. Some features are more expensive to offer, and thus are hidden |
| 10 | +behind a commandline flag, `--python.EmulateJython`. |
| 11 | + |
| 12 | +## Importing Java classes and packages |
| 13 | + |
| 14 | +In the default mode, Java classes can only be imported through the `java` |
| 15 | +package. Additionally, only Java classes can be imported, not packages. In |
| 16 | +Jython compatibility mode, importing works more directly, at the cost worse |
| 17 | +performance for import failures in the general case. |
| 18 | + |
| 19 | +#### Normal mode |
| 20 | + |
| 21 | +Suppose you want to import the class `sun.misc.Signal`, normal usage looks like |
| 22 | +this: |
| 23 | + |
| 24 | + import java.sun.misc.Signal as Signal |
| 25 | + |
| 26 | +For the `java` namespace, you do not have to repeat the `java` name (but can): |
| 27 | + |
| 28 | + import java.lang.System as System |
| 29 | + |
| 30 | +#### Jython mode |
| 31 | + |
| 32 | +In Jython mode, Java packages can be imported and traversed, and they can be |
| 33 | +imported directly without going through the `java` module. |
| 34 | + |
| 35 | + import sun.misc.Signal as Signal |
| 36 | + |
| 37 | + import org.antlr |
| 38 | + |
| 39 | + type(org.antlr.v4.runtime) # => module |
| 40 | + org.antlr.v4.runtime.Token |
| 41 | + |
| 42 | +The downside of this is that everytime an import fails (and there are many |
| 43 | +speculative imports in the standard library), we ask the Java classloader to |
| 44 | +list currently available packages and traverse them to check if we should create |
| 45 | +a Java package. This slows down startup significantly. |
| 46 | + |
| 47 | +## Interacting with Java objects |
| 48 | + |
| 49 | +Once you get hold of a Java object or class, interaction in both modes works |
| 50 | +naturally. Public fields and methods can be read and invoked as expected. |
| 51 | + |
| 52 | +## Subclassing Java classes and implementing interfaces with Python classes |
| 53 | + |
| 54 | +This is not supported at all right now, there's no emulation available even in |
| 55 | +Jython compatibility mode. We have not seen many uses of this in the wild. Let |
| 56 | +us know if this is of interest to you! |
| 57 | + |
| 58 | +## Catching Java exceptions |
| 59 | + |
| 60 | +By default this is not allowed, because of the additional cost of checking for |
| 61 | +Java exceptions in the except statement execution. However, in Jython |
| 62 | +compatibility mode, the common case of catching a Java exception directly works: |
| 63 | + |
| 64 | + import java.lang.NumberFormatException as NumberFormatException |
| 65 | + import java.lang.Integer as Integer |
| 66 | + |
| 67 | + try: |
| 68 | + Integer.parseInt("99", 8) |
| 69 | + except NumberFormatException as e: |
| 70 | + pass |
| 71 | + |
| 72 | +Note that even in this mode, Java exceptions are never caught by generic except |
| 73 | +handlers, so this *will not* work: |
| 74 | + |
| 75 | + import java.lang.Integer as Integer |
| 76 | + |
| 77 | + try: |
| 78 | + Integer.parseInt("99", 8) |
| 79 | + except: |
| 80 | + pass |
0 commit comments