No java imports in smali? - java

I was doing some experiments today in android source.
Let me tell the complete thing,
I compiled framework.jar from android source and decompiled it and generated smali source and kept it aside. Then from CyanogenMod repo I added the commits of a feature to android source and compiled framework.jar again and again decompiled smali source to see the changes in terms of smali so that I can port them over to my ROM.
The feature I am porting requires importing of certain classes e.g import dalvik.system.VMRuntime and extra coding for utilization of those imported classes. So now my problem is, I am only able to see the extra coding i.e utilization of those classes in the smali code but not those imports. So when I port only the smali code I get java.lang.NoSuchMethodError in logcat which shows that it is unable to find that method. The reason is clear because the necessary class is not imported then how to do it in smali code? i see no way to do that in smali and due to which the newly introduced methods don't work.
Any feasible solution to this?

The only thing an import does in java is make it so that you can mention a class without having to specify the full package name. In smali, there are no imports - everything always uses the fully qualified class name that includes the package.
As such, your problem is definitely not related to imports. It sounds like you are trying to use a method that simply doesn't exist on the device.
You can disassemble the framework jars from your device and find the definition of the dalvik.system.VMRuntime and see what methods are available. Or alternately add some reflection calls and log the info to logcat.
It's worth noting that VMRuntime is not part of the public API, and it may not be present or consistent on all devices or future versions of Android.

(I don't know smali, so there may be a much better solution)
No Java program ever requires any import statement. To use e.g. ArrayList you need to either import it or refer to it in full, as java.util.ArrayList.
There is a significant difference between e.g. a C++ #include and a Java import. A C++ #include directly inserts code in your program, typically the declaration for a class you are using. The process of getting the declarations is divided into two stages in Java. First the compiler determines the fully qualified class name, then it uses its own library and the classpath to find the declaration for that name. Java import is used only in calculating the fully qualified class name, and so is not needed for any class that is only referred to by its fully qualified name.
Perhaps you could pre-process the code you are adding to replace e.g. VMRuntime with dalvik.system.VMRuntime etc. so that you can compile it with no imports.
Here is an example of a short program that uses java.util classes, in different ways, without any import:
public class Test {
public static void main(String[] args) {
java.util.List<String> list = new java.util.ArrayList<String>();
list.add("bbb");
list.add("aaa");
java.util.Collections.sort(list);
System.out.println(list);
}
}

Related

Is it bad to import unused packages?

For instance when you work in a team at the same file and have only a partial understanding of the different packages imported needed for the code to work. You change some code in this file and find out some code become redundant because of that. You delete that part and now do not know if the whole code still depends on all packages or not.
[Of course bad can be objectified in many ways: speed, read-abilty etc.]
Yes. For a couple of reasons:
It can be confusing for a human looking at the code seeing imports that may or may not be used.
There may be import conflicts with several classes imported with the same name. This will require all but one of the similar class names to be referenced by their full qualified name in the code.
For these reasons, java will emit warnings if an import statement isn't needed and IDEs have ways to automatically delete unused imports.
Note, I didn't mention speed or performance changes, I think javac is smart enough to know not to use any unneeded imports so the compiled class will be just as if you didn't import it.
You should always only use as few of the imports as necessary, and don't use complete package imports like java.util.*. Today's IDE's usually support this with an "Organize Imports" operation during which unused imports are removed.
If you have bunch of unused imports and you modify the code, there is a chance you will add/change code that refers to classes which are covered by the unused imports. Then you won't notice that you accidentally utilized them even though that might not be your intent.
If you only have the minimum imports, if you add code that refers to a new class, the compiler will immediately notify you by showing errors, and giving you the possibility to choose which class you intend to use.
Also if you use imports beyond what is currently referenced in your program, you increase the chance to break your program for future releases of Java or the libraries you use.
Example: If your program only uses java.util.HashSet but you still import java.util.* and you use another 3rd party library from where you import com.mylib.*, your code might compile. If in a future release the 3rd party library adds a class named com.mylib.HashSet, you're code might not compile anymore because the compiler might not be able to tell which class you wanted to use (e.g. java.util.HashSet or com.mylib.HashSet).
Have you imported only java.util.HashSet only and e.g. com.mylib.SomeUtil in the first place, your code would still compile with the new version of the 3rd party lib.
Importing unused packages would NOT affect your speed, as explained here
However...it does make it more difficult to read your code if you have useless packages imported. If you are using NetBeans, you can always remove unused imports with Ctrl + Shift + I.

Replacing java class?

I'm working on a sandbox feature for my java antivirus, and I've come into a question: Does the specified package on a class matter for compilation?
Example:
I'm running a program that wants to use Runtime.getRuntime().exec(), when the classloader attempts to load that to run a method, does it check the package qualified in the file, if they exist? I would prefer not to try and change files in the JVM, but to simply load ones from a different package. I can accomplish the loading and such, but my only dilemma, will it crash and burn? Inside the java, it would be registered as say, java.lang.Runtime, but the compiled code will say for example pkg.pkg.Runtime and will it need to extend the old runtime? My guess is that extending the old runtime would just break it. Does anyone know anything about this? I'm working on making a testable example, but I'm still a bit away and wanted to get some answers, as well as this might benefit some people.
Does the specified package on a class matter for compilation?
Yes it does matter. A class called pkg.pkg.Runtime() cannot be loaded as if it was java.lang.Runtime.
Furthermore, if my memory is correct, the JVM has some additional security measures in it to prevent normal applications from injecting classes into core packages such as java.lang.
If you need to change the behaviour of the java.lang.Runtime class (for experimental purposes!) then I think you will need to put your modified version on the boot classpath, ahead of the "rt.jar" file.
However:
This level of tinkering can easily result in JVM instability; i.e. hard JVM crashes that are difficult to diagnose.
If your aim is to produce a "production quality" tool, then you will find that things that involve tinkering with the JVM are not considered acceptable. People are going to be very suspicious of installation instructions that say things like "add this to your installed JVM's bootclasspath".
Distributing a "tinkered with" JVM may fall foul of Oracle's Java licensing agreement.
My advice would be to look for a less intrusive way of doing what you are trying to do. For instance, if you are trying to do virus checking, either do it outside of the JVM, or in a custom application classloader.
You commented:
I have a custom classloader, my question is: If I compile a class that is labelled as say, pkg.pkg.Runtime, can I register in my classloader as java.lang.Runtime?
As I said above, no you can't. A bytecode file has the classname embedded in it. If you attempt to "pull a swifty" by loading a class with a different name, the JVM will throw an Error.
And:
If not, then how can I replace the class? If the compiled package name has to equal the request referenced naming, then can I modify the .class file to to match, or perhaps compile it as if it were in the java.lang package?
That's what you would have to do. You need to name the class java.lang.Runtime in the source code and compile it as such.
But what I meant by my advice above is that you should use do the virus checking in the class loader. Forget about trying to replace / modify the behaviour of Runtime. It is a bad idea for the reasons I listed above.

Do I have to use "package" term in every class?

Firstly, I'm trying to learn Java with Java, A Beginner's Guide, 4th Edition. I use Ubuntu as my OS and Netbeans as my IDE. I need to create a project to create a class when using Netbeans.
Here is my hello world app.
class First{
public static void main(String args[])
{
System.out.println("Hello!");
}
}
But this returns a lot of errors. When I put package first; line to top line of my Java class it runs. But, the book isn't using package term. Is this a rule of Netbeans, or what I need to know about this?
You never need to put a class in a package. However, it is almost always a good idea. This is something that Netbeans aggressively tries to encourage you to do.
For small projects, using the default package (that is, a file without a package statement) is OK. However, once your project grows and starts adding external libraries, bad things can happen. What if someone else decided to use the default package and happened to have an identically-named class? Now, since you're both in the same package, collisions can occur!
Your file structure should also reflect your package. That is, a file in package com.myurl.helloworld should be located in a folder called com/myurl/helloworld. This is for the same reasons as above.
Also, and you probably haven't gotten here in your studies, you cannot import classes from the default package, or use the package-private visibility modifier in a default package class.
That's because the author of Java, A Beginner's Guide, 4th Edition most likely used the "default package". This way, you don't have to include any package. A package is a namespace declaration.
What the heck is a namespace declaration!?
A namespace declaration is simply a package which is made to organize your classes. For an instance, if you're going to have multiple classes for, let's say your GUI, and multiple classes for algorithms, blending them together is always a bit confusing. Sorting them in different packages, however is a superior solution.
There is also a naming convention which you should follow if other people are going to look at your code. Packages should be named after a top-level domain. I tend to create SourceForge projects and then I end up with something like this:
net.sourceforge.softwarename.security, net.sourceforge.softwarename.gui, etc...
Also note that you should never use upper case when naming your package. More info here.
You're going to encounter lots of situations like these when learning to programming. They're all a part of the game. You'll just have to figure out a bit by yourself.
The best I can do for you is to recommend Eclipse. Also, when learning Java, I would suggest that you do not use an IDE at ALL! That's because you'll learn to code independently. It's up to you, though.
No you don't need to put in a package into your class UNLESS you are going to import it to another class that will be in it's own file. This is where protected type variables come in when you don't want to make them priviate but only want the subclasses (or child classes) access to them. You are also missing your public statement for your class so it should look like
public class First{
public static void main(String[] args){
System.out.println("Hello!");
}
}
Package represents a directory that contains related group of classes and interfaces.
A package is a namespace that organizes a set of related classes and
interfaces. Conceptually you can think of packages as being similar to
different folders on your computer. You might keep HTML pages in one
folder, images in another, and scripts or applications in yet another.
Because software written in the Java programming language can be
composed of hundreds or thousands of individual classes, it makes
sense to keep things organized by placing related classes and
interfaces into packages.
Below you can find some good discussions regarding java packages:
Java packages com and org
Are there best practices for (Java) package organisation?
Java com.* package namespace

why autoimport only java.lang package?

I know that the package java.lang is auto-imported by every java program we write, hence all the classes in it are automatically available to us.
My question is why not auto import java.util and other packages too? That sure will save some typing :)
So please explain why is this not done.
A good reason not to autoimport too much is to avoid namespace clashes. If everything in java.util was imported automatically and then you wanted to refer to a different class named 'Map', for example, you would have to refer to it by its fully-qualified name.
In response to other answers in this thread, import does not actually modify the internal representation of your class files. In fact, here is a link to the JVM spec describing the class file structure: see that imports are not stored anywhere.
All the good IDE's will resolve your imports automatically, only prompting when there is a conflict (two packages with the same classname).
Because java.lang have the core Java language classes, and java.util for example not.
But some other languages, like Groovy automatically imports java.util for you :)
I think the idea behind java.lang is that these classes all have some connection to the language and runtime which is special, and can't be implemented on your own. Primitive wrappers, VM security and permissions and inspection, package and class loading -- all things that must be built-in to the Java system. Everything in java.util, like collections, while incredibly useful, could be implemented in pure Java. Some parts of it (time zones come to mind) have even been implemented by third-party libraries even better.
Or at least, that was true back in the Java 1.0 days. Today, for example, Iterator is also integral to the language, since it's automatically used by for-each loops, right? But backwards-compatibility was always a big thing with Java, so we get to live with this inconsistency forever.
I came across with namespace collision even with java.lang.System (our application contains a System named class). An explicit import solved my problem, but it took some minutes until I pointed out that com.mycompany.classes.System isn't imported automatically for identifier System by Eclipse because it already exists in java.lang.
Anyways, it isn't a good idea to pollute the class scope with too much identifiers, because your code will org.classes.**look** com.application.**like** com.classes.**this**.
Auto-importing java.lang is a good idea because it contains the very core classes and interfaces used in java.
#gameover, May be every java program needs the class that comes from java.lang,
but the java.util class contains the class that my be need or not that is depended on programmer. So the java have the default configuration for java.lang but we need to import to java.util classes according to our program.
java.lang package provides fundamental classes to built java programs. Object is the root of class hierarchy so it needs to be available for every programmer whether the programmer is beginner or expert.
While if we talk about other packages they are used for enlarging the programs. For example, java.util package which is only used when Collection classes are needed. While in every program Collection classes are not used while basic datatypes are essential for every java program.
To avoid unnecessary load of other classes in program other packages are not auto imported while essential package java.lang is auto imported.
There are different reason for to become java.lang package is default
1)
Actually ,whatever we are declaring variable in java program.that will be stored in object,Object class is available in java.lang package.it is super class of class hierarchy,Many we have performed operation in object class method like thread programming.
2)
Many time it is required class for developing program ,that class is available in java.lang package,
So, it is necessary to import,when java people developed jdk, it was default package,
Auto importing also leads some memory issue and some times it may conflict.
Eg: Date Type in java & SQL .
Also whatever the base core java objects are defined in Java.lang package .
Eg: any datatype & return type all are declared in java.lang package so to do some basic program also we need this package imports.
Without java.lang package, development is not possible.
But without java.util, java.io or any other packages, we can still write any number of programs.
That is the reason why java.lang package is being imported by default.

Why is each public class in a separate file?

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

Categories

Resources