How are java classes loaded and how do I figure out where/when/why a class is loaded?

Azianese :

So I kind of understand what a java ClassLoader is in that it prepares compiled .class files for the JVM. I just barely understand how it works in that it tries to load a class through a series of steps which recursively call parent ClassLoaders. What I'm failing to understand is how a ClassLoader is determined. That is, how is a ClassLoader chosen for a class?

I'm asking this question now because I've essentially run into the following problem: I can't cast a child class to the implemented interface.

The class looks like the following:

public class AccountBoImpl implements AccountBo {
...
}

Here is the end of my (slightly edited) stacktrace:

15:49:47.269 [DefaultThreadPool-7] ERROR com.company.app.kem.biz.ao - 
java.lang.ClassCastException: com.company.app.department.bo.AccountBoImpl cannot be cast to com.company.domain.core.biz.AccountBo
    at com.company.domain.core.biz.AccountBOF.findBySomething(AccountBOF.java:62) ~[Client-1.0.0-SNAPSHOT.jar:na]
    at com.company.domain.shared.biz.applogic.balances.SiteAccountBalanceProcessor.setUnbilledUsage(SiteAccountBalanceProcessor.java:347) ~[Domain-1.0.0-SNAPSHOT.jar:na]

Here, the packages are different between AccountBoImpl and AccountBo (the interface which AccountBoImpl implements). I want to know what determines how these classes are loaded. For example, why is AccountBo being loaded with the com.company.domain.core.biz package when I imported com.company.app.billing.bo.AccountBo;? I know that at some point in this code, a Module class is called which supposedly initializes the classes. But I'm not sure what to look for in this Module class.

Lastly, to figure out why this class is being loaded incorrectly, I assume I need to find out where/when it's being loaded. But how do I do that? I only know that classes are loaded on an as-need basis (whatever that really means), but I don't know how I would go about solving this problem. For example, with a variable, I can debug/step into the code to see when a variable value is being assigned. But for a class...? What is it I'm looking for? I know that in this code base, we have legacy code that provides many of the same classes as the newer code, but how do I use this information to solve my problem?

I apologize in advance if I'm leaving critical information out or if this question seems vague. I'm not sure how to approach this problem as I've just learned that ClassLoaders existed yesterday.

Holger :

The decision, how to resolve the simple name AccountBo, is made at compile time.

If you truly have an import com.company.app.billing.bo.AccountBo; statement your class, it is impossible that the implements AccountBo clause gets resolved to a class of a different package.

And the ClassCastException is acknowledging precisely that, as it says that your class is not assignable to com.company.domain.core.biz.AccountBo.

So there is no problem with class loaders and no problem with a wrongly resolved identifier. Your class implements com.company.app.billing.bo.AccountBo, but within the method findBySomething of class com.company.domain.core.biz.AccountBOF is an attempt to cast an instance of your class to com.company.domain.core.biz.AccountBo which it does not implement.

Generally, having public classes with such easy-to-confuse names is not a good idea.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=164463&siteId=1