What I am trying to do: I want to have a pre-compiled java byte-code file, and be able to place a "mark" in some places. Later I want to analyze this file using ASM and replace mark with some code. So, how can I implement this? Currently I am trying to do it, by inserting invocations of empty static method, but I still feeling like I am doing something wrong. Is there a better way to do this?
P.S. If more general, I want to have some precompiled class template, for example:
public class Main {
public static void Main(String... args){
System.out.println("Program starts!");
//I want to insert code here
System.out.println("Bye!");
}}
There is no Java statement without a predefined meaning, well, maybe with the exception of the empty statement ; which doesn’t create code that you can find in the byte code. There are annotations, but these can only be used to mark another code fragment, not to create a stand-alone statement within your code.
So you have to choose a statement to assign it the meaning of being a mark in your template code and your solution of using an invocation of a dedicated empty method is a perfect candidate for such a mark. Since it’s new meaning does not rely on the kind of statement but on the target method which resides in a class whose name is distinguishable from all other classes, there is no conflict between your mark and other statements.
But you should consider that the framing class code is rather trivial compared to the code you will generate when implementing a compiler for any non trivial language. In most cases, the logic of patching the generated code into an existing code will exceed the complexity of just generating a complete class file.
If you really have large pieces of unchanging code you should consider placing them into their own classes and generate classes using or extending them. This simplifies the code generation and avoids code duplication (the same reason why these techniques are used in manually written code).
Related
I'm writing a program in Java. I find that reading and debugging code is easiest when the paradigm techniques are consistent, allowing me very quickly assume where and what a problem is.
Doing this has, as you might guess, made my programming much faster, and so I want to find a way to enforce these rules.
For example, lets say I have a method that makes changes to the state of an object, and returns a value. If the method is called outside of the class, I don't ever want to see it resolve inside parameter parentheses, like this:
somefunction(param1, param2, object.change_and_return());
Instead, I want it to be done like this:
int relevant_variable_name = object.change_and_return();
somefunction(param1, param2, relevant_variable_name);
Another example, is I want to create a base class that includes certain print methods, and I want all classes that are user defined to be derived from that base class, much in the way java has done so.
Within my objects, is there a way I can force myself (and anyone else) to adhere to these rules? Ie. if you try to run code that breaks the rules, it will terminate and return the custom error report. Also, if you write code that breaks the rules, the IDE (I use eclipse) will recognize it as an error, underline and call the appropriate javadoc?
For the check and underline violations part:
You can use PMD, it is a static code analyzer.
It has a default ruleset, and you can write custom rules matching what you need.
However your controls seem to be quite complex to express in "PMD language".
PMD is available in Eclipse Marketplace.
For the crash if not conform part
There see no easy way to do it.
Hard/complex ways could be:
Write a rule within PMD, run the analysis at compile time, parse the report (still at compile time) and return an error if your rule is violated.
Write a Java Agent doing the rule check and make it crash the VM if the rule is violated (not sure it is really feasable, agents are meant for instrumentation).
Use reflection anywhere in your code to load classes, and analyze loaded class against your rules and crash the VM if the rule is violated (seriously don't do this: the code would be ugly and the rule easily bypassable).
I am currently taking a project management class and the professor gave this assignment to compare two .java files methods and fields in all cases programmatically. I don't think it's actually possible to do but maybe I am wrong!
The assignment spec is as following (its extremely ambiguous I know)
In this assignment, you are required to write a comparison tool for two
versions of a Java source file.
Your program takes as input two .java files representing those two versions
and reports the following atomic changes:
1. AM: Add a new method
2. DM: Delete a method
3. CM: Change the body of a method (note: you need to handle the case where a method is
relocated within the body of its class)
4. AF: Add a field
5. DF: Delete a field
6. CFI: Change the definition of an instance field initializer (including (i) adding an initialization to a
field, (ii) deleting an initialization of a field, (iii) making changes to the initialized value of a field,
and (iv) making changes to a field modifier, e.g., private to public)
So that's what I am working with and my approach was to use reflection as it allows you to do everything but detect differences in the method body.
I had considered the idea that you could create a parser but that seemed ridiculous, especially for a 3 credit undergrad class in project management. Tools like BeyondCompare don't list what methods or fields changed, just lines that are different so don't meet the requirements.
I turned in this assignment and pretty much the entire class failed it with the reason as "our code would not work for java files with external dependencies that are not given or with java files in different projects" - which is completely correct but also I'm thinking, impossible to do.
I am trying to nail down a concrete answer as to why this is not actually possible to do or learn something new about why this is possible so any insight would be great.
What you got wrong here is that you have started to examine the .class files (using reflection). Some of the information listed above is not even available at that stage (generics, in-lined functions). What you need to do is parsing the .java files as text. That is the only way to actually solve the problem. A very high-level solution could be writing a program that:
reads the files
constructs a specific object for each .java file containing all the informations that needs to be compared (name of the functions, name of the instance variables, etc)
compares the constructed objects (example: addedFunctions = functionsFromA.removeAll(functionsFromB)) to provide the requested results
Note: if this is an assignment, you should not be using solutions provided by anybody else, you need to do it on your own. Likely you will not get a single point if you use a library written by somebody else.
By now my average class contains about 500 lines of code and about 50 methods.
IDE is Eclipse, where I turned “Save Actions” so that methods are sorted in alphabetical order, first public methods, and then private methods.
To find any specific method in the code I use “Quick Outline”. If needed, “Open Call Hierarchy” shows the sequence of methods as they called one by one.
This approach gives following advantages:
I can start typing new method without thinking where to place it in the code, because after save it will be placed by Eclipse to appropriate place automatically.
I always find public methods in the upper part of the code (don’t have to search the whole class for them)
However there are some disadvantages:
When refactoring large method into smaller ones I’m not very satisfied that new private methods are placed in different parts of code and therefore it’s little bit hard to follow the code concept. To avoid that, I name them in some weird way to keep them near each one, for example: showPageFirst(), showPageSecond() instead of showFirstPage(), showSecondPage().
May be there are some better approaches?
Organize your code for its audiences. For example, a class in a library might have these audiences:
An API client who wants more detail on how a public method works.
A maintainer who wants to find the relevant method to make a small change.
A more serious maintainer who wants to do a significant refactoring or add functionality.
For clients perusing the source code, you want to introduce core concepts. First we have a class doc comment that includes a glossary of important terms and usage examples. Then we have the code related to one term, then those related to another, then those related to a third.
For maintainers, any pair of methods that are likely to have to change together should be close by. A public method and its private helper and any constants related to it only should show up together.
Both of these groups of users are aided by grouping class members into logical sections which are separately documented.
For example, a collection class might have several mostly orthogonal concerns that can't easily be broken out into separate classes but which can be broken into separate sections.
Mutators
Accessors
Iteration
Serializing and toString
Equality, comparability, hashing
Well, naming your methods so that they'll be easier to spot in your IDE is really not good. Their name should reflect what they do, nothing more.
As an answer to your question, probably the best thing to do is to split you class into multiple classes and isolate groups of methods that have something in common in each of such classes. For example , if you have
public void largeMethodThatDoesSomething() {
//do A
//do B
//do C
}
which then you've refactored such that:
public void largeMethodThatDoesSomething() {
doA();
doB();
doC();
}
private void doA() {};
private void doB() {};
private void doC() {};
you can make a class called SomethingDoer where you place all these 4 metods and then use an instance of that class in your original class.
Don't worry about physically ordering your methods inside the class, if you can't see it just use Ctrl-O and start typing the method name and you will jump straight to it.
Having self-describing method names results in more maintainable code than artificially naming them to keep them in alphabetical order.
Hint: learn your shortcut keys and you will improve your productivity
Organizing the way you described sounds better than 99% of the Java code I have seen so far. However, on the other side, please make sure your classes don't grow too much and methods are not huge.
Classes should usually be less than 1000 lines and methods less than 150.
I have a very large and bloated class and I want to split it into separate files, but it should be completely transparent to the user and compatible with existing projects that use the class.
In particular, I have my own ImageMatrix class and it defines a ton of unary functions, a ton of binary functions with a scalar, a ton of binary functions with another image, etc. To keep the class clean and maintainable, I wish to put each class of operators in a separate file.
Is there a way to just cut/paste these methods into a file and include them in the source?
So I wish that I can still do this, but the methods actually reside in different files:
ImageMatrix img = new ImageMatrix(800, 600, 3);
img.clear(0.5f, 0.0f, 0,0f);
img.addSelf(anotherImg);
img.normalize();
img.abs();
img.addSelf(0.5);
Each method is around 15-30 lines of code because the implementations are extremely optimized for performance, the like of which is impossible to achieve with Bufferedimage or even a plain int[]. There is a lot of code duplication, which is the main reason to group similar methods together. If I add a function or if I change global behavior (like error checking), I can easily keep things coherent.
Unfortunately it is not possible to split a Java class definition into multiple files.
Try to restructure your code so that a huge class definition isn't necessary. Often this means exposing some state through getter and setter methods, and writing supporting classes which use these methods to add functionality to your main class.
In your case, you might consider adding supporting classes like ImageFilters, or even something more narrow like ImageNormalizer if you like very small classes.
You can also use delegate methods. This means the definitions of your methods are still in ImageMatrix, but they are implemented in another class. Depending on the complexity of your methods this could reduce the amount of code in ImageMatrix.
class ImageMatrix {
MatrixHelperOne helperOne = new MatrixHelperOne();
...
public void complexMethod1(Arg arg) {
helperOne.complexMethod1(arg);
}
...
}
Well, you could create a more generic class and put more generic methods there and then have ImageMatrix extends that one. Also, if you have a lot of matrix manipulation functions you will probably end up with a lot of code duplication, i.e. repeating the same code in different methods instead of moving the common code into an aux method and calling it from different places, etc.
You can't split a Java class across files. If each of your methods is self-contained, you could create classes with static methods. So to a certain extent, you would only need to cut and paste code.
This is language agnostic, but I'm working with Java currently.
I have a class Odp that does stuff. It has two private helper methods, one of which determines the max value in an int[][], and the other returns the occurrences of a character in a String.
These aren't directly related to the task at hand, and seem like they could be reused in future projects. Where is the best place to put this code?
Make it public -- bad, because Odp's functionality is not directly related, and these private methods are an implementation detail that don't need to be in the public interface.
Move them to a different class -- but what would this class be called? MiscFunctionsWithNoOtherHome? There's no unifying theme to them.
Leave it private and copy/paste into other classes if necessary -- BAD
What else could I do?
Here's one solution:
Move the method that determines te max value in a two-dimensional int array to a public class called IntUtils and put the class to a util package.
Put the method that returns the occurrences of a character in a String to a puclic class called StringUtils and put the class to a util package.
There's nothing particularly bad about writing static helper classes in Java. But make sure that you don't reinvent the wheel; the methods that you just described might already be in some OS library, like Jakarta Commons.
Wait until you need it!
Your classes wil be better for it, as you have no idea for now how your exact future needs will be.
When you are ready, in Eclipse "Extract Method".
EDIT: I have found that test driven development give code that is easier to reuse because you think of the API up front.
A lot of people create a Utility class with a lot of such methods declared as static. Some people don't like this approach but I think it strikes a balance between design, code reuse, and practicality.
If it were me, I'd either:
create one or more Helper classes that contained the methods as static publics, naming them as precisely as possible, or
if these methods are all going to be used by classes of basically the same type, I'd create an abstract base class that includes these as protected methods.
Most of the time I end up going with 1, although the helper methods I write are usually a little more specific than the ones you've mentioned, so it's easier to come up with a class name.
I not know what the other languages do but I have the voice of experience in Java on this: Just move to the end-brace of your class and write what you need ( or nested class if you prefer as that is accepted canonical convention in Java )
Move the file scope class ( default access class right there in the file ) to it's own compilation unit ( public class in it's own file ) when the compiler moans about it.
See other's comments about nested classes of same name if differing classes have the same functionality in nested class of same name. What will happen on larger code bases is the two will diverge over time and create maintainability issues that yield to Java's Name of class as type of class typing convention that forces you to resolve the issue somehow.
What else could I do?
Be careful not to yield to beginner impulses on this. Your 1-2 punch nails it, resist temptation.
In my experience, most large projects will have some files for "general" functions, which are usually all sorts of helper functions like this one which don't have any builtin language library.
In your case, I'd create a new folder (new package for Java) called "General", then create a file to group together functions (for Java, this will just be a class with lots of static members).
For example, in your case, I'd have something like: General/ArrayUtils.java, and in that I'd throw your function and any other function you need.
Don't worry that for now this is making a new class (and package) for only one function. Like you said in the question, this will be something you'll use for the next project, and the next. Over time, this "General" package will start to grow all sorts of really great helper classes, like MathUtils, StringUtils, etc. which you can easily copy to every project you work on.
You should avoid helper classes if you can, since it creates redundant dependencies. Instead, if the classes using the helper methods are of the same type (as kbrasee wrote), create an abstract superclass containing the methods.
If you do choose to make a separate class do consider making it package local, or at least the methods, since it may not make sense for smaller projects. If your helper methods are something you will use between projects, then a library-like approach is the nicest to code in, as mentioned by Edan Maor.
You could make a separate project called utils or something, where you add the classes needed, and attach them as a library to the project you are working on. Then you can easily make inter-project library updates/fixes by one modification. You could make a package for these tools, even though they may not be that unified (java.util anyone?).
Option 2 is probably your best bet in Java, despite being unsatisfying. Java is unsatisfying, so no surprise there.
Another option might be to use the C Preprocessor as a part of your build process. You could put some private static functions into file with no class, and then include that file somewhere inside a class you want to use it in. This may have an effect on the size of your class files if you go overboard with it, of course.