Is it possible to ignore java access modifiers during compilation? (besides the javac plugin)
I have a java agent that should affect modifiers in runtime. I would be interested in trying to compile the files by tricking (or somehow asking it not to look at the modifiers) the compiler.
Edit:
I managed to do one thing:
I created a mask class for the target class, made changes to it. Using shadow jar, I moved the mask and then deleted it. Using java agent, I loaded my class instead of the target one. And yes, it works. Perhaps someone will find some other options.
I don't think what you ask is possible (but more research is needed). What you can do is to use reflection in your code.
For a field f in a class C, you can do:
C.class.getField("f").setAccessible(true)
See the Javadoc for reference
Is it possible to set the #ExtensionMethod for the whole project?
For example if I extend Object with a method isNull(), would it be possible to use that in the whole project with only define the #ExtensionMethod in for example a config class and use it everywhere without declaring it on each class?
Lombok contributor here:
No. The primary reason is 'surprises' - lombok would then be having an effect on a source file that has zero mentions of lombok, anywhere in side it (no types or imports; a CMD+F for lombok would produce zero results), and yet, doesn't compile without it.
Lombok does have a config system (lombok.config) and that would be the place to define some fully qualified class names to be treated as automatically considered sources of extension methods for all java source files in the directory where this config file appears and all subdirs of that directory. But, this feature doesn't exist right now, and won't, until I and other major contributors hold a bit of a debate on whether we want to open this can of worms.
Some meet-in-the-middle solution where there is a list of 'default extensions', but you still need to enable it by annotating the class with #DefaultExtensionMethods or what not (or just #ExtensionMethod and nothing more, with no arguments) might be where we draw the line. I'll keep it in mind.
At least on my machine when I put 2 Java class files on the same folder, without making them part of the same package, they already see one another, so from one file I can call a public class from the other file and vice-versa.
Questions:
Is this the general case or a coincidence that may not work on every platform?
If this is not a coincidence, I am guessing the purpose of packages is to allow you to organize your class files and make they share stuff, even if they are spread across different folders and paths. Is this correct or I am missing something?
If no package name is specified, the classes in the file go into a special unnamed package. And this is the same case for all files with no explicit package specification. Hence, they all fall into the special unnamed package, and exhibit the behavior that you are seeing.
You might want to go through this for a better understanding.
If they're in the same directory then they're in the same package, or are you copying .class files around after they've been written by the compiler?
Packages are a way of organising classes into a namespace. There are plenty of reasons to do this, the best bet is to start with the tutorial.
I sure it is general case, but it is bad approach.
You are right, but more general reason to use package is to separate namespaces, for example, you have to create Car class, but there are many people who want to use this classname, thats why you have to use package, for example: com.yourcompany.yourproject. In such case you can use your Car class from your package without implicitly defining package and you also can use other Car classes in such manner: new com.google.general.Car();
In the java rules, it is recommend to use domain name right-to-left for providing unique package name.
is there any way to do the following. so i have a project.jar file, inside it i need to modify the string passed to some method of let's say classA.class. for example, let's say this classA.class has a method named
change(String a, String b)
what i all want is to do the following as the first line of the code inside this method as follows:
a = a + "hi";
i want to modify the .class file directly, without needing to recompile everything again. then after that i would update the jar file with the new class file. is it possible? if yes can anyone show an example? thanks a lot in advance!
Yes it's possible with byte code editors. Commonly you can use aspectj together with compile time weaving to modify a class file. You can also use libraries such as BCEL, cglib etc.
However, for the use case you are describing you typically don't need to edit a class file. You can just wrap your object in a proxy or modify it's behaviour using AoP style of programming (as supported by e.g., aspectj)
There are tools to manipulate byte code dynamically, such as ASM: http://asm.ow2.org/
another way could be instrumentation. when you are loading the class you could manipulate the bytecode before using it. there are some good libraries for this, for example javassist from jboss. i think aspectJ works similar.
but why you want to change the bytecode, compile it and add it to a jar file again? are you needing the source code? perhaps you could use some de-compiler to get the source code, if you need it. a good tool is http://java.decompiler.free.fr/.
I recently started learning Java and found it very strange that every Java public class must be declared in a separate file. I am a C# programmer and C# doesn't enforce any such restriction.
Why does Java do this? Were there any design considerations?
Edit (based on a few answers):
Why is Java not removing this restriction now in the age of IDEs? This will not break any existing code (or will it?).
I have just taken a C# solution and did just this (remove any file that had multiple public classes in them) and broke them out to individual files and this has made life much easier.
If you have multiple public classes in a file you have a few issues:
What do you name the file? One of the public classes? Another name? People have enough issues around poor solution code organization and file naming conventions to have one extra issue.
Also, when you are browsing the file / project explorer its good that things aren't hidden. For example you see one file and drill down and there are 200 classes all mushed together. If you have one file one class, you can organize your tests better and get a feel for the structure and complexity of a solution.
I think Java got this right.
According to the Java Language Specification, Third Edition:
This restriction implies that there must be at most one such type per compilation unit. This restriction makes it easy for a compiler for the Java programming language or an implementation of the Java virtual machine to find a named class within a package; for example, the source code for a public type wet.sprocket.Toad would be found in a file Toad.java in the directory wet/sprocket, and the corresponding object code would be found in the file Toad.class in the same directory.
Emphasis is mine.
It seems like basically they wanted to translate the OS's directory separator into dots for namespaces, and vice versa.
So yes, it was a design consideration of some sort.
From Thinking in Java
:
There can be only one public class per compilation unit (file).
The idea is that each compilation unit has a single public interface represented by that public class. It can have as many supporting “friendly” classes as you want. If you have more than one public class inside a compilation unit, the compiler will give you an error message.
From the specification (7.2.6)
When packages are stored in a file system (?7.2.1), the host system may choose to enforce the restriction that it is a compile-time error if a type is not found in a file under a name composed of the type name plus an extension (such as .java or .jav) if either of the following is true:
The type is referred to by code in other compilation units of the package in which the type is declared.
The type is declared public (and therefore is potentially accessible from code in other packages).
This restriction implies that there must be at most one such type per compilation unit.
This restriction makes it easy for a compiler for the Java programming language or an implementation of the Java virtual machine to find a named class within a package; for example, the source code for a public type wet.sprocket.Toad would be found in a file Toad.java in the directory wet/sprocket, and the corresponding object code would be found in the file Toad.class in the same directory.
In short: it may be about finding classes without having to load everything on your classpath.
Edit: "may choose" seems like it leaves the possibility to not follow that restriction, and the meaning of "may" is probable the one described in RFC 2119 (i.e. "optional")
In practice though, this is enforced in so many platform and relied upon by so many tools and IDE that I do not see any "host system" choosing to not enforce that restriction.
From "Once upon an Oak ..."
It's pretty obvious - like most things are once you know the design reasons - the compiler would have to make an additional pass through all the compilation units (.java files) to figure out what classes were where, and that would make the compilation even slower.
(Note:
the Oak Language Specification for Oak version 0.2 (postcript document): Oak was the original name of what is now commonly known as Java, and this manual is the oldest manual available for Oak (i.e. Java).
For more history on the origins of Java, please have a look at the Green Project and Java(TM) Technology: An Early History
)
It's just to avoid confusion in the sense that Java was created with simplicity in mind from the perspective of the developer. Your "primary" classes are your public classes and they are easy to find (by a human) if they are in a file with the same name and in a directory specified by the class's package.
You must recall that the Java language was developed in the mid-90s, in the days before IDEs made code navigation and searching a breeze.
If a class is only used by one other class, make it a private inner class. This way you have your multiple classes in a file.
If a class is used by multiple other classes, which of these classes would you put into the same file? All three? You would end up having all your classes in a single file...
That's just how the language designers decided to do it. I think the main reason was to optimize the compiler pass-throughs - the compiler does not have to guess or parse through files to locate the public classes. I think it's actually a good thing, it makes the code files much easier to find, and forces you to stay away from putting too much into one file. I also like how Java forces you to put your code files in the same directory structure as the package - that makes it easy to locate any code file.
It is technically legal to have multiple Java top level classes in one file. However this is considered to be bad practice (in most cases), and some Java tools may not work if you do this.
The JLS says this:
When packages are stored in a file
system (§7.2.1), the host system may
choose to enforce the restriction that
it is a compile-time error if a type
is not found in a file under a name
composed of the type name plus an
extension (such as .java or .jav) if
either of the following is true:
The type is referred to by code in other compilation units of the package in which the type is declared.
The type is declared public (and therefore is potentially accessible from code in other packages).
Note the use of may in the JLS text. This says that a compiler may reject this as invalid, or it may not. That is not a good situation if you are trying to build your Java code to be portable at the source code level. Thus, even if multiple classes in one source file works on your development platform, it is bad practice to do this.
My understanding is that this "permission to reject" is a design decision that is intended in part to make it easier to implement Java on a wider range of platforms. If (conversely) the JLS required all compilers to support source files containing multiple classes, there would be conceptual issues implementing Java on a platform which wasn't file-system based.
In practice, seasoned Java developers don't miss being able to do this at all. Modularization and information hiding are better done using an appropriate combination of packages, class access modifiers and inner or nested classes.
Why is java not removing this restriction now in the age of IDEs? This will not break any existing code (or will it?).
Now all code is uniform. When you see a source file you know what to expect. it is same for every project. If java were to remove this convention you have to relearn code structure for every project you work on, where as now you learn it once and apply it everywhere. We should not be trusting IDE's for everything.
Not really an answer to the question but a data point none the less.
I grepped the headers of my personal C++ utilty library (you can get it yourself from here) and almost all of the header files that actually do declare classes (some just declare free functions) declare more than one class. I like to think of myself as a pretty good C++ designer (though the library is a bit of a bodge in places - I'm its only user), so I suggest that for C++ at least, multiple classes in the same file are normal and even good practice.
It allows for simpler heuristics for going from Foobar.class to Foobar.java.
If Foobar could be in any Java file you have a mapping problem, which may eventually mean you have to do a full scan of all java files to locate the definition of the class.
Personally I have found this to be one of the strange rules that combined result in that Java applications can grow very large and still be sturdy.
Well, actually it is an optional restriction according to Java Language Specification (Section 7.6, Page No. 209) but followed by Oracle Java compiler as a mandatory restriction. According to Java Language Specification,
When packages are stored in a file system (§7.2.1), the host system
may choose to enforce the restriction that it is a compile-time error
if a type is not found in a file under a name composed of the type
name plus an extension (such as .java or .jav) if either of the
following is true:
The type is referred to by code in other compilation units of the package in which the type is declared.
The type is declared public (and therefore is potentially accessible from code in other packages).
This restriction implies that there must be at most one such type per
compilation unit. This restriction makes it easy for a Java compiler
to find a named class within a package.
In practice, many programmers choose to put each class or interface
type in its own compilation unit, whether or not it is public or is
referred to by code in other compilation units.
For example, the source code for a public type wet.sprocket.Toad would
be found in a file Toad.java in the directory wet/sprocket , and the
corresponding object code would be found in the file Toad.class in the
same directory.
To get more clear picture let's imagine there are two public classes public class A and public class B in a same source file and A class have reference to the not yet compiled class B. And we are compiling (compiling-linking-loading) class A now while linking to class B compiler will be forced to examine each *.java files within the current package because class B don’t have it’s specific B.java file. So In above case, it is a little bit time consuming for the compiler to find which class lies under which source file and in which class the main method lies.
So the reason behind keeping one public class per source file is to actually make compilation process faster because it enables a more efficient lookup of the source and compiled files during linking (import statements). The idea is if you know the name of a class, you know where it should be found for each classpath entry and no indexing will be required.
And also as soon as we execute our application JVM by default looks for the public class (since no restrictions and can be accessible from anywhere) and also looks for public static void main(String args[]) in that public class. Public class acts as the initial class from where the JVM instance for the Java application (program) is begun. So when we provide more than one public class in a program the compiler itself stops you by throwing an error. This is because later we can’t confuse the JVM as to which class to be its initial class because only one public class with the public static void main(String args[]) is the initial class for JVM.
You can read more on Why Single Java Source File Can Not Have More Than One public class