Gaining access to package-access members by creating the same package name - java

I have a question about a sneaky way to gain access to package-access members that occurred to me. Specifically, I want to extend a class - let's call it com.acme.Foo - to add some functionality. This is pure addition: all current methods of Foo would be supported just by delegating to the superclass's method. However, there is no accessible constructor of Foo, so I can't extend the class and my implementation won't pass the "isA" test for being a Foo. There is no interface that expresses Foo-ness that I can use instead of inheritance.
This is where the sneaky thought occurred to me: Foo has a package-access constructor, so why not just create a package com.acme in my source folder and create an InheritableFoo class in that package:
package com.acme;
public class InheritableFoo extends Foo {
public InheritableFoo() {
super();
}
}
Now I can implement my extension to Foo by extending InheritableFoo, since that DOES have an accessible constructor.
This feels all wrong, and somehow unethical: I'm not respecting the decision the original programmer made when he or she decided to not expose a constructor for Foo. But it could be the case that they simply adopted the "deny everything until there's a reason for it" approach. Either way, is there anything fundamentally wrong with this idea? Am I going to cause myself problems in the future if I go this route, and if so, why?

You are correct regarding the fact that you can "sneak" in a class of your own into another package and get access to package restricted elements.
This will however only as long as the author of com.acme.foo distribute his code as source or an unsealed package. Should the author of this package distribute it as a sealed jar (which is quite common I believe) your approach will no longer work.
From Sealing Packages within a JAR File
Packages within JAR files can be optionally sealed, which means that
all classes defined in that package must be archived in the same JAR
file.

Related

How does Java know which class to use in this example?

I am beginning to learn the principles of OOP and inheritance, and I came across this question while writing some code:
Suppose there is a package which contains a class called ClassA. Then, in a separate folder, I have another class called MyClass. Inside the same folder as MyClass, I have another class called ClassA, which is unrelated to the ClassA in the package. When I write the code for MyClass, I make it extend ClassA.
Which ClassA does MyClass extend from? Does MyClass inherit the ClassA which is in the imported package, or does MyClass inherit the ClassA which is in the same folder as MyClass? Would the code even compile?
I am trying to understand this from a theory perspective before diving into examples.
what you're looking at is a Statically scoped language which will work its way out of its inner scope, all the way to its outter scopes.
In this case, since import Class A is declared directly inside the file to which it is first called, it will use import Class A and stop.This will be its default behavior.
It will not carry on to look at the packaged Class A because it found one already, declared inside of the same class file.
This is the default behavior of java's (static) scope hierarchy.
IF it had not found an import of Class A imported inside the same file, it would reach out to its package to search for one.
This is very useful when declaring like variables. Do a little research how statically scope languages work.
If it is easier for you to understand, you can be explicit in your intentions by declaring exactly which Class A you would like though.
Just a side note- this is more of a programming languages question than directly a java question, but since you ask specifically for java, we only need to cover the simple specific answer. if you would like to know more, i can direct you (or tell you) more about statically vs dynamically scoped languages.
I suppose it is worth noting that if you decide to import both Class As even from your package (which you do NOT need to do) you would have to explicitly declare which you would like.
In that situation, to make it perfectly clear to the compiler you would probably want to do something like extends otherPackage.ClassA, and use the full reference name to extend the classA from the other package. If you want to use the one from the package MyClass is in, then just don't import the other ClassA and do extends ClassA
Since you're new to programming, I'm going to explain it in really simple words. Say there is a package called Salads. In that package, you have a class called Caesar. Then, you have another package called People. In that package, you have another class called Caesar. Obviously, Salads.Caesar refers to Caesar salad, and People.Caesar refers to a person named Caesar. But both classes have the same name: Caesar.
So when you're writing java code, java looks in two places for class definitions:
classes defined in the same folder (because they are implicitly in the same package if they are in the same folder assuming you're following all the normal rules.
classes defined in any imported packages
So the question is asking if you just say Caesar in the code, will it recognize it as the one in the same folder or the one in the imported package? Well, this is a bad question to ask because first of all, you should not name your classes so ambiguously. Secondly, if it can't be helped, you should always refer to the fully qualified name in your code.
If you mean People.Caesar then type People.Caesar and if you mean Salads.Caesar, type Salads.Caesar. Don't take shortcuts. You can only take shortcuts if there is no ambiguity. The compiler will probably complain about it anyway asking you to specify. AKA your code will not work unless you change all references of Caesar to Salads.Caesar or People.Caesar.
Packages in Java is a mechanism to encapsulate a group of classes,
interfaces and sub packages. Many implementations of Java use a
hierarchical file system to manage source and class files. It is easy
to organize class files into packages. All we need to do is put
related class files in the same directory, give the directory a name
that relates to the purpose of the classes, and add a line to the top
of each class file that declares the package name, which is the same
as the directory name where they reside.
in the top of java files, you have import that you can choose what class from what package you mean of course as #Jason said too if the class you want its in your package you don't need to tell it explicitly and compiler know that but if its in another package you have to tell him explicitly.
assume you have FirstClass.java in src folder and another in mycodes folder when in your class you import FirstClass you mean FirstClass.java that exist in src folder and when you import mycodes.FirstClass you mean FirstClass in mycodes folder.
your class can be member of packag.when you extend class that you class are in package A when you extend SomeClass you mean SomeClass that is in package A and if you want extend other class that is in other package like B you must extend B.SomClass
Here is another information about packages in java

java dynamic class loading that avoids java.lang.IllegalAccessError

Oracle JavaDocs explains that IllegalAccessError is
"Thrown if an application attempts to access or modify a field, or to
call a method that it does not have access to."
I try to load a class dynamically and I get this exception.
if I understand correctly when you use a classloader to load a class with a private package dynamically IllegalAccessError happens
the class I am trying to load is using
org.xml.sax.helpers.SecuritySupport
which also states in their description in the following url
http://grepcode.com/file/repository.springsource.com/org.apache.xmlcommons/com.springsource.org.apache.xmlcommons/1.3.4/org/xml/sax/helpers/SecuritySupport.java
that
Unfortunately, we can't load the class using reflection
* because the class is package private. And the class has
* to be package private so the APIs aren't exposed to other
* code that could use them to circumvent security. Thus,
* we accept the risk that the direct reference might fail
* on some JDK 1.1 JVMs, even though we would never execute
* this code in such a case. Sigh...
how can I dynamically load it anyway? I have to get it to work.
also if I get an error when I use a classloader, I cannot recover from that, so how can I know in advance that I cannot load this class?
thanks in advance to anyone who helps
The statement “we can't load the class using reflection because the class is package private” doesn’t make any sense, as can be shown easily:
package somepackage;
class BaseClass {
public static void main(String[] args) throws ReflectiveOperationException {
BaseClass obj=(BaseClass)
Class.forName("somepackage.SubClass").newInstance();
obj.aMethod();
}
void aMethod() {
System.out.println("base class");
}
}
class SubClass extends BaseClass {
#Override
void aMethod() {
System.out.println("method overridden by subclass");
}
}
This works flawlessly, printing method overridden by subclass replicated the actual use case of that SecuritySupport class.
However, since that class obviously serves the purpose of allowing a transition between Java 1.1 and Java 1.2, it might be possible that there were such restrictions twenty years ago, when this transition happened.
Your use case, however, is entirely different. You say that you are trying to load a class which “is using org.xml.sax.helpers.SecuritySupport”, which doesn’t imply that it is using said class via Reflection, but as shown above, that doesn’t matter anyway. It either case, it would only work, if the class is in the same package, whether you load the class “dynamically” or not.
There are only two possible scenarios.
If the class is truly within the same package, which at runtime implies that it also has been loaded by the same class loader, which would require that is also part of the JRE, if the JRE’s org.xml.sax.helpers package defines a SecuritySupport class, then the class can access the class within the same package.
If you are trying to load a class via a different ClassLoader from a different code source, it will not be of that package, even if you’d give it a qualified name of the org.xml.sax.helpers.SomeClass form. If the JRE’s org.xml.sax.helpers package happens to define a SecuritySupport class, all non-JRE classes would be in a different package. When it tries to access that class, which is not part of the official API, it doesn’t work.
Note that all standard class loaders follow a delegation model trying to resolve a name through their parent class loader first, which is the reason why they all would prefer the JRE’s org.xml.sax.helpers.SecuritySupport class, if there is one. With non-standard class loaders, you could have different, unrelated classes with that qualified name, being in different runtime packages.
In that second scenario, the question arises, why your class is using that class. In 2017, there’s rarely a need to differentiate between Java 1.1 and Java 1.2 and the functionality offered by that class is also only relevant for a class within the privileged code source of the JRE (or different code sources with different privileges in general).

Different behaviour of Class literal and Class.forName for package local classes

Only for example lets consider the class ClassFileAssembler from the sun.reflect package.
This class is a package local class:
class ClassFileAssembler implements sun.reflect.ClassFileConstants {...
So we can not use even its name ClassFileAssembler, we can not import it directly - it will lead to a compiler error.
However we can create a package named sun.reflect in our project and use the ClassFileAssembler name internally in this package - Java compiler will think that we are inside the ClassFileAssembler's package.
If so, why not to try to get a reference to a class object, i.e. ClassFileAssembler.class?
Class<ClassFileAssembler> classFileAssemblerClass = ClassFileAssembler.class;
Unexpectedly this code leads to a run-time error: java.lang.IllegalAccessError: tried to access class sun.reflect.ClassFileAssembler from class sun.reflect.Test.
However we still able to get the ClassFileAssembler class object:
Class<ClassFileAssembler> aClass = (Class<ClassFileAssembler>)Class.forName("sun.reflect.ClassFileAssembler");
It works fine and gives us a full class description.
So, the questions are:
1) What is the difference between techniques, how Class.forName0 retrieves reference to class object, and how .class does it?
2) Why do they have such different security checks?
3) What's the reason to protect .class reference in such way?
4) Do these techniques use different class loaders?
Class.forName don't care about whether a class is package local or not. It is when you attempt to use that class that access is checked. BTW if you do setAccessible(true) you can by pass these access restrictions.
The Reflection library allows you to do many things you cannot do in Java code. The Java has rules as to what you can and cannot do. e.g. you cannot set a final field outside a constructor or more than once. Note: the JVM doesn't have this restriction and at runtime you can use reflections to change it.
The reason this class is package local is to restrict access of the class to code outside this package. This doesn't mean you cannot access it if you really try, but it is less likely you will access it without serious thought being put into it. e.g. when I import classes in my IDE it often suggests classes from com.sun.* which are unlikely to be the right choice. (MY IDE can be set up to ignore these, but I often seem for find some new package I don't want)
The reason Reflections can do this is to support functionality such a Serialization. With Serialization you need to be able to serialize class outside the package of the Serialization library and obtain fields and reset them when deserializing. Reflections is also used by many Inversion of Control libraries though I suspect this is not what they had in mind when they design it.
If you check the javadoc of Class#forName, you will see that:
Note that this method does not check whether the requested class is accessible to its caller.
there is no difference. but you cannot access the static field .class of the package private (no modifier) class ClassFileAssembler.
everyone could access the Class instances, but the fields are protected.
in fact no one designed to protect .class reference this way, it's side effect of protecting other fields.
i dont think so.

Java packages and classes

I'm building a very simple library in Java, which will be packaged in a single Jar. It should only expose one class: World. The World class uses the subclasses of the Block class, which is in the same package (com.yannbane.a), and doesn't provide a lot of functionality itself, but needs to be extended. I planned to create another package, com.yannbane.a.blocks, which would have all the block types (subclasses).
The directory/package structure should, therefor, look like this:
com/
yannbane/
a/
World.java
Block.java
blocks/
Brick.java
Stone.java
However, in order for the subclasses of Block to actually extend the Block class, I needed to make the Block class public. This destroys my goal of having the Jar file only expose a single class, World. I also need to make the subclasses public so the World could use them.
How can I retain this package and directory structure but still have my Jar only expose the World class, not other classes?
If this is a matter of encapsulation, and all you want to expose to the world is the "World" class, then it does not matter if the unexposed classes are located in the same package or if they are inner classes in the same package.
At any rate, they will not be accessible to the users of your API. I believe encapsulation is more important here than the "logical" organization that you want to give your files. Because if you locate all your classes in the same package, then you will not have these problems and you will achieve the level of encapsulation that you are seeking. Perhaps what Java is telling you is that these classes are so inherently related that you should place them all in the same package.
Make the classes public but their constructors protected.
You still technically expose the classes - other packages are aware of them - but no other packages can instantiate those objects.
Even though the Block subclasses are in a different package from Block (com.yannbane.a and com.yannbane.blocks) they will be able to invoke the protected parent constructor, because protected members are accessible from the same package or from an inheriting object.

Should I keep the package name when extending a class?

I plan to extend a JSF renderer. The package name is oracle.adfinternal.view.faces.renderkit.rich
Should the extended class be in the same package structure:
oracle.adfinternal.view.faces.renderkit.rich
or even oracle.adfinternal.view.faces.renderkit.rich.[subpackage]
or can/should I put it into my own package? com.company.renderkits.
I suppose package-private variables might be interfered with if I put this into my own package name?
Any thoughts?
In general, you should put your extended classes in your own package.
The package-private access level should be used by closely connected classes, possibly written by the same developer, who knows all the implementation details. This is not the case if you extend a class with some functionality.
All that said, there are a few occasions where you need to place your class in the package of the superclass as a workaround, but remember, this is an ugly hack, and try hard to avoid it.
You should put the class into your own package. There shouldn't be any compilation/access problems. The superclass already sees what it needs to see.
I suppose package-private variables might be interfered with if I put this into my own package name?
This is true, but normally the extending class shouldn't worry about this. The to-be-extended class would have used the protected modifier for this otherwise.
You should not add things to other entities (companies, person) packages. They could make a class with the same name (and same package of course) at a later date. They could also choose to seal their JAR files as well which would prevent you from adding classes to their packages.
The purpose of packages is to give each entity their own unique namepsace in which to create types.
In your case I would name the package something like: com.foobar.oracle.adfinternal.view.faces.renderkit.rich where "com.foobar" is the reverse domain name of your entity (if you don't have one pick something that is unique).

Categories