module Javalib:sig
..end
User interface for using the Javalib.
typeaccess =
[ `Default | `Private | `Protected | `Public ]
Visibility modifiers.
type
attributes = {
|
synthetic : |
(* | correspond to the attribute, not to the flag (cf. JVM Spec se8 table 4.7-C and §4.7.8) | *) |
|
deprecated : |
|||
|
other : |
Generic attributes common to classes, fields and methods.
type
visibility =
| |
RTVisible |
| |
RTInvisible |
visibility modifiers for annotations. An annotation may either be visible at
run-time (RTVisible
) or only present in the class file without being
visible at run-time (RTInvisible
). (Note that there exists a third
visibility at the Java source level, but as it corresponds to the
source-only visibility they are not in the class file anymore.)
type
field_kind =
| |
NotFinal |
| |
Final |
| |
Volatile |
Field kind
typeconstant_attribute =
[ `Double of float
| `Float of float
| `Int of int32
| `Long of int64
| `String of JBasics.jstr ]
type
class_field = {
|
cf_signature : |
|||
|
cf_class_signature : |
|||
|
cf_generic_signature : |
|||
|
cf_access : |
|||
|
cf_static : |
|||
|
cf_synthetic : |
(* | correspond to the flag ACC_SYNTHETIC, not to the Attribute (cf. JVM Spec se8 table 4.5-A) | *) |
|
cf_enum : |
|||
|
cf_kind : |
|||
|
cf_value : |
|||
|
cf_transient : |
|||
|
cf_annotations : |
|||
|
cf_other_flags : |
|||
|
cf_attributes : |
Fields of classes.
type
interface_field = {
|
if_signature : |
|||
|
if_class_signature : |
|||
|
if_generic_signature : |
|||
|
if_synthetic : |
(* | correspond to the flag ACC_SYNTHETIC, not to the Attribute (cf. JVM Spec se8 table 4.5-A) | *) |
|
if_value : |
(* | a constant_attribute is not mandatory, especially as it can be initialized by the class initializer <clinit>. | *) |
|
if_annotations : |
|||
|
if_other_flags : |
|||
|
if_attributes : |
Fields of interfaces are implicitly public
, static
and
final
.
type
any_field =
| |
InterfaceField of |
| |
ClassField of |
val get_field_signature : any_field -> JBasics.field_signature
val get_class_field_signature : any_field -> JBasics.class_field_signature
val get_field_visibility : any_field -> access
val is_static_field : any_field -> bool
val is_final_field : any_field -> bool
type 'a
implementation =
| |
Native |
| |
Java of |
type
method_annotations = {
|
ma_global : |
(* | annotations that are for the whole method. | *) |
|
ma_parameters : |
(* |
| *) |
type
method_parameter_attribute = {
|
mp_name : |
|
mp_final : |
|
mp_synthetic : |
|
mp_mandated : |
Attribute proper to a method parameter.
type 'a
concrete_method = {
|
cm_signature : |
|||
|
cm_class_method_signature : |
|||
|
cm_static : |
|||
|
cm_final : |
|||
|
cm_synchronized : |
|||
|
cm_strict : |
(* | Correspond to flag ACC_STRICT, which shows if we are in FP-strict mod or not. | *) |
|
cm_access : |
|||
|
cm_generic_signature : |
|||
|
cm_bridge : |
|||
|
cm_varargs : |
|||
|
cm_synthetic : |
(* | correspond to the flag ACC_SYNTHETIC, not to the Attribute (cf. JVM Spec se8 table 4.6-A) | *) |
|
cm_other_flags : |
|||
|
cm_exceptions : |
|||
|
cm_attributes : |
|||
|
cm_parameters : |
|||
|
cm_annotations : |
|||
|
cm_implementation : |
type
abstract_method = {
|
am_signature : |
|||
|
am_class_method_signature : |
|||
|
am_access : |
|||
|
am_generic_signature : |
|||
|
am_bridge : |
|||
|
am_varargs : |
|||
|
am_synthetic : |
(* | correspond to the flag ACC_SYNTHETIC, not to the Attribute (cf. JVM Spec se8 table 4.6-A) | *) |
|
am_other_flags : |
|||
|
am_exceptions : |
|||
|
am_attributes : |
|||
|
am_parameters : |
|||
|
am_annotations : |
|||
|
am_annotation_default : |
(* | If the method is in an annotation interface, then | *) |
An abstract method cannot be final, synchronized, strict or private.
type 'a
jmethod =
| |
AbstractMethod of |
| |
ConcreteMethod of |
val get_method_signature : 'a jmethod -> JBasics.method_signature
val get_class_method_signature : 'a jmethod -> JBasics.class_method_signature
val get_method_visibility : 'a jmethod -> access
val is_static_method : 'a jmethod -> bool
val is_final_method : 'a jmethod -> bool
val is_synchronized_method : 'a jmethod -> bool
type
inner_class = {
|
ic_class_name : |
|||
|
ic_outer_class_name : |
|||
|
ic_source_name : |
|||
|
ic_access : |
|||
|
ic_static : |
|||
|
ic_final : |
|||
|
ic_synthetic : |
|||
|
ic_annotation : |
(* |
| *) |
|
ic_enum : |
|||
|
ic_other_flags : |
|||
|
ic_type : |
type 'a
jclass = {
|
c_name : |
|||
|
c_version : |
|||
|
c_access : |
|||
|
c_final : |
|||
|
c_abstract : |
|||
|
c_super_class : |
|||
|
c_generic_signature : |
|||
|
c_fields : |
|||
|
c_interfaces : |
|||
|
c_consts : |
(* | needed at least for unparsed/unknown attributes that might refer to the constant pool. | *) |
|
c_sourcefile : |
|||
|
c_deprecated : |
|||
|
c_enclosing_method : |
(* | introduced with Java 5 for local classes (defined in methods' code). The first element is innermost class that encloses the declaration of the current class. The second element is the method that encose this class definition. cf JVM spec se8 table 4.7-C and §4.7.7. | *) |
|
c_source_debug_extention : |
(* | Introduced in Java 5 for debugging purpose (no semantics defined). cf JVM spec se8 table 4.7-C and §4.7.11. | *) |
|
c_inner_classes : |
|||
|
c_synthetic : |
(* | correspond to the flag ACC_SYNTHETIC, not to the Attribute (cf. JVM Spec se8 table 4.1-A) | *) |
|
c_enum : |
|||
|
c_annotations : |
|||
|
c_other_flags : |
|||
|
c_other_attributes : |
|||
|
c_methods : |
type 'a
jinterface = {
|
i_name : |
|||
|
i_version : |
|||
|
i_access : |
|||
|
i_interfaces : |
|||
|
i_generic_signature : |
|||
|
i_consts : |
(* | needed at least for unparsed/unknown attributes that might refer to the constant pool. | *) |
|
i_sourcefile : |
|||
|
i_deprecated : |
|||
|
i_source_debug_extention : |
(* | Introduced in Java 5 for debugging purpose (no semantics defined). cf JVM spec se8 table 4.7-C and §4.7.11. | *) |
|
i_inner_classes : |
|||
|
i_annotation : |
(* |
| *) |
|
i_annotations : |
|||
|
i_other_attributes : |
|||
|
i_other_flags : |
|||
|
i_fields : |
|||
|
i_methods : |
Interfaces cannot be final and can only contains abstract
methods. Their super class is java.lang.Object
.
type 'a
interface_or_class =
| |
JInterface of |
| |
JClass of |
val get_name : 'a interface_or_class -> JBasics.class_name
Returns the fully qualified name of a class_name
.
val get_consts : 'a interface_or_class -> JBasics.constant array
Returns the constant pool of a class or interface.
val get_access : 'a interface_or_class -> [ `Default | `Public ]
Returns the access type of a class or interface.
val get_sourcefile : 'a interface_or_class -> string option
Returns the source file associated to the parsed bytecode used to build the given class or interface.
val is_deprecated : 'a interface_or_class -> bool
Returns true
if the use of the given interface or class is deprecated,
false
otherwise.
val is_final : 'a interface_or_class -> bool
Returns true
if the given interface or class is final, false
otherwise.
val get_inner_classes : 'a interface_or_class -> inner_class list
Returns the list of inner classes defined in the given class or interface.
val get_initializer : 'a interface_or_class -> 'a concrete_method option
Returns the initializer of the given class or interface, if defined.
val get_other_attributes : 'a interface_or_class -> (string * string) list
val get_other_flags : 'a interface_or_class -> int list
val defines_method : 'a interface_or_class -> JBasics.method_signature -> bool
defines_method ioc ms
returns true
if ioc
defines a method with a signature equal
to ms
, false
otherwise.
val get_method : 'a interface_or_class ->
JBasics.method_signature -> 'a jmethod
get_method ioc ms
returns the method with the signature ms
in the
interface or class ioc
.
Not_found
if such a method can't be found.val get_concrete_method : 'a interface_or_class ->
JBasics.method_signature -> 'a concrete_method
get_concrete_method ioc ms
returns the method with the signature
ms
in the interface or class ioc
.
Not_found
if such a
method can't be found or if the method is not concrete.val get_methods : 'a interface_or_class -> 'a jmethod JBasics.MethodMap.t
Returns the map of all the methods defined in the given class or interface.
val get_concrete_methods : 'a interface_or_class ->
'a concrete_method JBasics.MethodMap.t
Returns the map of all the concrete methods defined in the given class or interface.
val defines_field : 'a interface_or_class -> JBasics.field_signature -> bool
defines_field ioc fs
returns true
if ioc
defines a field with a signature equal
to fs
, false
otherwise.
val get_field : 'a interface_or_class -> JBasics.field_signature -> any_field
get_field ioc fs
returns the field with the signature fs
in the
interface or class ioc
.
Not_found
if such a field can't be found.val get_fields : 'a interface_or_class -> any_field JBasics.FieldMap.t
Returns the map of all the fields defined in the given class or interface.
val cf_iter : (class_field -> unit) -> 'a interface_or_class -> unit
val if_iter : (interface_field -> unit) -> 'a interface_or_class -> unit
val f_iter : (any_field -> unit) -> 'a interface_or_class -> unit
val cf_fold : (class_field -> 'b -> 'b) ->
'a interface_or_class -> 'b -> 'b
val if_fold : (interface_field -> 'b -> 'b) ->
'a interface_or_class -> 'b -> 'b
val f_fold : (any_field -> 'b -> 'b) -> 'a interface_or_class -> 'b -> 'b
val cm_iter : ('a concrete_method -> unit) -> 'a interface_or_class -> unit
val am_iter : (abstract_method -> unit) -> 'a interface_or_class -> unit
val m_iter : ('a jmethod -> unit) -> 'a interface_or_class -> unit
val cm_fold : ('a concrete_method -> 'b -> 'b) ->
'a interface_or_class -> 'b -> 'b
val am_fold : (abstract_method -> 'b -> 'b) ->
'a interface_or_class -> 'b -> 'b
val m_fold : ('a jmethod -> 'b -> 'b) -> 'a interface_or_class -> 'b -> 'b
val map_concrete_method : ?force:bool ->
('a -> 'b) -> 'a concrete_method -> 'b concrete_method
map_concrete_method f cm
lazily applies f
to the implementation of cm
(if the method is native, it does nothing but changing the type). The
application is lazy: f
is not applied until Lazy.force
is called on
the implementation: be careful if you use side-effects.
val map_interface_or_class : ?force:bool ->
('a -> 'b) -> 'a interface_or_class -> 'b interface_or_class
map_interface_or_class f ioc
lazily applies f
to all non-native method
implementations of the interface or class ioc
. The application of f
is
lazy (cf Javalib.map_concrete_method
).
val map_interface_or_class_context : ?force:bool ->
('a concrete_method -> 'a -> 'b) ->
'a interface_or_class -> 'b interface_or_class
map_interface_or_class_context f ioc
lazily applies f
to all non-native
method implementations of the interface or class ioc
, giving the concrete
method being transformed as argument to f
. The application of f
is lazy (cf Javalib.map_concrete_method
).
val map_concrete_method_with_native : ('a implementation -> 'b implementation) ->
'a concrete_method -> 'b concrete_method
map_concrete_method_with_native f cm
is equivalent to
Javalib.map_concrete_method
but allows to transform not only the code
representation but also the implementation type. It provides a way
to modify the nature of implementation to Native
if the code
could not be transformed or conversly to provide a generated code
for Native
implementation.
val map_interface_or_class_with_native : ('a implementation -> 'b implementation) ->
'a interface_or_class -> 'b interface_or_class
map_interface_or_class_with_native f ioc
is equivalent to
Javalib.map_interface_or_class
but allows to transform not
only the code representation but also the implementation type. It
provides a way to modify the nature of implementation to Native
if the code could not be transformed or conversly to provide a
generated code for Native
implementation.
val map_interface_or_class_with_native_context : ('a concrete_method ->
'a implementation -> 'b implementation) ->
'a interface_or_class -> 'b interface_or_class
map_interface_or_class_with_native_context f ioc
is equivalent to
Javalib.map_interface_or_class_context
but allows to transform not
only the code representation but also the implementation type. It
provides a way to modify the nature of implementation to Native
if the code could not be transformed or conversly to provide a
generated code for Native
implementation.
val remove_invokedynamic : JCode.jcode interface_or_class ->
JBasics.method_signature ->
int ->
prefix:string ->
JCode.jcode interface_or_class *
JCode.jcode interface_or_class
remove_invokedynamic ioc ms pp prefix
returns a couple of
interface or classes (ioc',ioc_lambda)
, where ioc'
is a
modified version of ioc
and ioc_lambda
is a forged class
implementing the functional interface of the lambda expression to
be found in ioc
at program point pp
of method ms
.
The class ioc'
contains two additional public static bridge
methods, named callsite_prefix_pp
and access_prefix_pp
, which
respectively wrap the callsite creation and the lambda method
call. The invokedynamic
instruction at program point pp
of
method ms
is replaced by an invokestatic
call to the
callsite_
bridge method.
The forged class ioc_lambda
, named prefix_pp
, captures the
arguments of the lambda expression in private fields, through its
constructor, which would normally be captured by the original
invokedynamic
instruction. The class ioc_lambda
also implements
the functional interface defined by the lambda expression by
calling the bridge method access_
created in ioc
.
Not_found
if method ms
can't be found in ioc
, and an
exception if pp
does not refer to an invokedynamic
instruction.val remove_invokedynamics_in_method : JCode.jcode interface_or_class ->
JBasics.method_signature ->
prefix:string ->
JCode.jcode interface_or_class *
JCode.jcode interface_or_class JBasics.ClassMap.t
remove_invokedynamics_in_method ioc ms prefix
iters the method
Javalib.remove_invokedynamic
on all the program points containing
invokedynamic
instructions in method ms
of class ioc
. The
result is a couple (ioc', cmap)
, where ioc'
is the rewritten
class and cmap
is a JBasics.ClassMap
containing all the forged
classes implementing the different functional interfaces associated
with each lambda expression. The prefix
is passed to
Javalib.remove_invokedynamic
in order to generate the forged class
names.
Not_found
if method ms
can't be found in ioc
val remove_invokedynamics : JCode.jcode interface_or_class ->
prefix:string ->
JCode.jcode interface_or_class *
JCode.jcode interface_or_class JBasics.ClassMap.t
remove_invokedynamics ioc prefix
iters the method
Javalib.remove_invokedynamics_in_method
on all the methods of class
ioc
. Some unique generated ids are concatenated to the prefix
in order to forge different class names associated to each
implementation of the functional interfaces.
type
class_path
The type of "compiled" class paths (jar (or zip) files are opened for efficiency).
val class_path : string -> class_path
class_path cp
opens a class path from the list cp
of
directories and jar (or zip) files separated by JFile.sep
. jar
(or zip) files in the given directories are also considered, but
they are not looked for recursively. If cp
is empty(""
), then
the current directory is used. Note: the order matters: the
search stops when a class file is found. Directories and jar (or
zip) files are read in the given order. When several directories
are given, the order of the jar (or zip) file inside those
directory are unspecified, but the jar (or zip) file of the first
directory will be read before the others.
Note : the following works :
try class_path (Sys.getenv "CLASSPATH")
with Not_found-> class_path ""
val close_class_path : class_path -> unit
Closes a class path.
val get_class : class_path ->
JBasics.class_name -> JCode.jcode interface_or_class
Parses a single class. It takes as argument the class name built
with JBasics.make_cn
.
This function does not check that the name of the parsed class is the
same as the argument class name.
JBasics.No_class_found
if the given class name cn
does not
correspond to a class file that can be found in the given class path.JBasics.Class_structure_error
if the class file does not match the
official specification (although it does not check the class file
entirely).val write_class : string -> JCode.jcode interface_or_class -> unit
write_class outputdir c
writes the class c
in the subdirectory of
outputdir
that correspond to the package name of c
.
Class_structure_error
if an opcode cannot be encoded in the available
place.val extract_class_name_from_file : string -> JBasics.class_name * string
extract_class_name_from_file f
recovers a class name and a class
path from the file f
.
Sys_error
if f
is not a file. f
must contain the .class
extension.val iter : ?debug:bool ->
(JCode.jcode interface_or_class -> unit) -> string -> unit
iter ~debug:false f filename
applies the function successively the
function f
on each classes specified by filename
. filename
is either a
valid class file, a valid jar (or zip) file, or a valid directory with jar
(or zip) files inside. The dirname of filename
is used as classpath. If
debug
is true
then the number of classes parsed when given a .jar file or
a directory is printed on the standard error output.
type
directories
Abstract type representing a list of directories.
val make_directories : string -> directories
make_directories directories
returns an abstract directories
type. The
string directories
must be a list of files separated by ":" under Unix or
";" under Windows. Only directories are filtered.
The following functions search for class files in the following order :
Dots in class names are interpreted as / (but not for jar files).
val read : directories ->
('a -> JCode.jcode interface_or_class -> 'a) ->
'a -> string list -> 'a
read directories f acc names
iterates f
over all classes specified by
names
. acc
is the initial accumulator value.
val transform : directories ->
string ->
(JCode.jcode interface_or_class ->
JCode.jcode interface_or_class) ->
string list -> unit
transform directories outputdir f names
applies f
to all classes
specified by names
, writing the resulting classes in outputdir
. Jar
files are mapped to jar files, zip files to zip files and the non-class
files are kept unchanged in the resulting archive.
val unparse_class : JCode.jcode interface_or_class -> Stdlib.out_channel -> unit
unparse_class ioc out
dump the class or interface ioc
into out
as a
.class
file. The distance between the offset of two successive
non-OpInvalid instructions is assumed to be at least the length of the
optimal coding for the first instruction (for example, iload_0 vs iload
0). The opcode may be encoded with the non-optimal form to fill the
available space.
Class_structure_error
if the length of an opcode produced is greater
than the available space (number of OpInvalid + 1) except if
JBasics.set_permissive
has been called with true
.module JPrint:sig
..end
Module gathering useful printing functions for basic types.