Recently I've been writing a compiler for a JVM programming language and I've realised a problem.
I would like to access a Java method from my programming language and also allow a Java method to access a method in my language. The problem is that I need to know the Java methods signature to call it in the bytecode I generate and vice versa.
I've been trying to think of any methods for how Scala does this. Here are my thoughts.
Scala accesses the .java files on the class path and parses them, extracting the method signatures from there.
.java files are compiled to .class files. The Java ASM library is then used to access the .class files and get the method signatures. The problem with this method is that the .java files must be compiled first.
.java files are loaded dynamically using reflection. The problem with this is I believe that the JVM doesn't allow for loading classes that are outside of the compilers class path.
Looking into Scala it works well with other JVM languages but I can't find information on exactly how it does it.
How does Scala get method signatures of other JVM language methods?
I think you are confusing class path and source path: there are no .java or .scala files on the class path, there are .class files (possibly inside .jars). So for dependencies (on the class path), you don't need to do anything special. They can have their own dependencies on your language, including previous versions of your project, but they are already compiled by definition.
Now, for mixed projects, where you have Java and your language on the source path, scalac does parse Java with its own parser (i.e. your option 1).
The problem with option 3 is not that "the JVM doesn't allow for loading classes that are outside of the compilers class path", but that reflection also only works on classes, not on source files.
Related
I am building an SDK in Java that has a public API and lots of internal 'private' classes. I would like to keep the public classes as public, but restrict the visibility of all the internals. I have to stick to Java 8, so I can't really take advantage of modularity introduced in later Java versions. We all know that in Java (unfortunately) packages are not really hierarchical - for example com.test1.test2 package is not really a sub-package of com.test1 and thus any class declared with package visibility modifier inside com.test1.test2 will not be visible from class declared inside com.test1. I can't really simply put all the classes in a single directory as that would make working with the project a nightmare.
I was wondering if it's possible to keep the file system hierarchy as usual, but declare classes as if they were inside a single package. For example create 2 files like these:
Class1 under path com/test1/test2/Class1.java
package com.test1;
class Class1 {}
Class2 under path com/test1/Class2.java
package com.test1;
class Class2 {}
So that logically, both of these classes would end up under the same package and be accessible from within one another using package visibility modifiers.
I know this is highly unusual and probably not supported by many IDEs, but I gave it a try using plain old javac and as long as I specify each source file by it's full path it compiles and runs just fine. Do you see any technical problems with that, other than (obviously) breaking the 'good practices'. If it makes any difference it is an Android project but written in Java.
If you want to keep two .java source files in separate directories, but having the Java classes belong to the same package, then you need multiple source root directories.
This is e.g. how test code is kept separate from regular code in a standard Maven project.
So, create the files as follows:
src1/com/test1/Class1.java
src2/com/test1/Class2.java
When compiling, have both src1 and src2 on the source path. Since the source path by default is the same as the classpath, that means using e.g. javac -cp src1;src2 -d bin com/test1/Class1.java, which will correctly find and compile Class2 if it is used by Class1. All the compiled .class files are consolidated in the single destination directory (bin in this example).
Having multiple source roots is common (all Maven projects have them, by default), so it is fully supported by IDEs.
Is it true that for every .class file that was created by the Scala compiler scalac, it is theoretically possible to define a .java file that gets compiled, by javac, to exactly this same .class file?
If not, can you give one or more non-trivial examples of constructions in Scala that get compiled to JVM bytecode for which there is no corresponding Java construction?
Is it true that for every .class file that was created by the Scala compiler scalac, it is theoretically possible to define a .java file that gets compiled, by javac, to exactly this same .class file?
No.
If not, can you give one or more examples of constructions in Scala that get compiled to JVM bytecode for which there is no corresponding Java construction?
class `class`
class is a legal name for a class in Scala, but not in Java, so it is impossible to get the Java compiler to generate a bytecode file with a class named class.
Scala being compiled inserts ScalaSig (scala signatures) into bytecode, i.e. Scala-specific kind of comments. These "comments" will be absent in class files compiled from Java sources.
Java being compiled can generate annotations (#) visible with Java reflection at runtime while Scala can't. Scala can only generate annotations visible at sources and class files but not at runtime with Java reflection although they can be visible at runtime with Scala reflection (because some info is written to ScalaSigs).
I am new to java programming.
Basically when we work in c/c++ programming we create dll files using .h and .c files,where .h file contains declarations and .c file contains definitions of those classes, functions.
when we want to use those functionalities of created .dll file in other project, we include .h in preprocessor declaration to tell compiler about declarations of variables,functions and we provide respective dll file path during compilation so that at linker stage it communicates with dll.
Here is my question how do they manage this in java programming because it doesn't contain any header files. it has only .java files where these files are combined and created JAR file.when i want to use this jar file in another project we use "package" or "import" keyword but when it says import total file will be imported with logic and how do linker manage at compilation step??
how do they manage this in java programming because it doesn't contain any header files.
It manages this by placing all the information it needs for compiling against the class and at runtime (and possibly debugging) in the .class file so there is no need for additional information.
Often the source and javadoc are placed in JARs as well (sometimes the same JAR)
when i want to use this jar file in another project we use "package" or "import" keyword
You don't have to. This is just a short hand. You can use full package.ClassName and there is no need for an import. Note: this doesn't import any code or data, just allow you to use a shorter name for the class.
e.g. there is no difference between
java.util.Date date = new java.util.Date();
and
import java.util.Date;
Date date = new Date(); // don't need to specify the full package name.
when it says import total file will be imported with logic
There is no way, nor no need to do this. There is nothing like #include for example, and inlining only occurs at runtime, not compile time (except for constants known at compile time)
how do linker manage at compilation step
The linking and compiling to native code is performed at runtime. All the javac compiler does is check the validity of your code and generate byte code for the JVM to read.
Modern languages, Java (& C#) do not make a distinction between declaration and definition, so the concept of .H file is gone in these languages.
In many aspects (new languages) the dualism compile-time vs runtime is lost (mainly because they have strong reflection). Java Classes or JARs (or C# assemblies) have information required to compile (alike declarations). Java environment don't require special 'files for compilation'. The same JAR is 'compile file' and 'runtime binary dll'
Typical C thinking with .H, .C, .LIB files goes to niche (IMHO - I'm old C programmer and I feel good with new languages)
When we refer to a class className in jar, how does it know whether it's defined or not when there's no header files(like in c/c++) ?
Java works with classloaders. Classes are needed for compilation, since it will perform static type checking to ensure that you are using the correct signatures of every method.
After compiling them, though, they are not linked like you have in a C/C++ compiler so basically every .class file is standalone. Of course this means that you will have to provide compiled classed used by your program when you are going to execute it. So it's a little bit different from how C and C++ prepare executables. You don't actually have a linking phase at all, it is not needed.
The classloader will dinamically load them by adding them to the runtime base used by the JVM.
Actually there are many classloaders that are used by the JVM that have different permissions and properties, you can also invoke it explicitly to ask for a class to be loaded. What happens can also be a sort of "lazy" loading in which the compiled .class code is loaded just when needed (and this loading process can throw a ClassNotFoundException if the asked class is not inside the classpath)
When you run the Java compiler or your application itself, you can specify a classpath which lists all the jars and directories you're loading classes from. A jar just contains a bunch of class files; these files have enough metadata in them that no extra header files are necessary.
The classes in the jar file contain all the required information (class names, method signatures etc) so header files are not needed.
When you compile multiple classes javac is clever enough to compile dependencies automatically so the system still works.
It looks at the classpath and tries to load the class from there to get its definition.
Java files are compiled into class files which are java bytecode. These class files reside in a file structure where the top level is pointed to by the classpath variable. Compiling in C/C++ creates object files which can be linked into executable binaries. Java only compiles into bytecode files which are pulled in by the JVM at runtime. The following provide more explanation.
http://en.wikipedia.org/wiki/Java_bytecode
http://en.wikipedia.org/wiki/Java_compiler
http://en.wikipedia.org/wiki/Java_Virtual_Machine
I am a .Net developer starting Java development for Android and would like to know if it's correct to think of Java packages like .Net assemblies.
No.
The best comparison would be with a Java ARchive (Jar) file. Java uses packages to control the namespace, and is very similar to C#'s Namespaces.
Here is how I'd compare the environments
Java .Net
==== ====
Class Class
Package Namespace
Jar Assembly
No, I think a Java package would be more similar to a namespace
And an assembly would be more like a jar (I'm not so sure about this, as I'm much more familiar with Java than .Net... correct me if I'm wrong)
A Java package is like a namespace in .NET.
The equivalent to an assembly in Java is jar file.
A package in Java usually means just a namespaces for classes and interfaces, which in reality means a specific directory structure. Sometimes a .jar file is also referred to as a package. This is probably the closest you get to an assembly. A .jar file can also contain other data like images, or basically an kind of file since it is just a zip again with some specific content structure.
In any case: Usually when you read "package" in relation to "Java", some kind of namespaces (via folder structure, e.g.: com.mycompany.myproject) is meant. It doesn't help that some build tools refer to the process of building .jar file as "packaging" ;-)
Bear in mind that I'm far from a Java expert, but anyway, there it goes my take on this:
As pointed out by other answers, a package is not the equivalent to an Assembly. However, I don't fully agree with the idea of a .jar being the equivalent to an Assembly.
To me, a Java class (contained in a .class file) is closer to an Assembly than a .jar is. I'm saying this cause while the load unit for the CLR is the Assembly (which means all classes contained in that Assembly get loaded), the load unit for the JVM is a class (when the JVM needs a class, the ClassLoader does not load all the classes in the container jar, it just loads that specific needed class).
You can read more about java class loading here:
When does the JVM load classes?
and here:
http://www.lansa.com/support/notes/p0294.htm