Java与Python的import语句内存加载机制差异及内存占用疑问
嘿,这个问题问到点子上了,我来给你把这事儿说透~
首先先明确你听到的说法大部分是对的,但咱们得把细节掰扯清楚:
Java的import内存加载逻辑
Java里的import真的只是编译期的符号引用而已——它的作用就是让你写代码的时候不用每次都写类的全限定名(比如不用写java.util.ArrayList,直接写ArrayList),编译后的字节码里根本不会保留import语句,全是类的全限定名。
而JVM的类加载是标准的懒加载(延迟加载):只有当你的代码真正用到某个类的时候(比如创建这个类的实例、调用它的静态方法/字段、甚至用反射去引用它),JVM的类加载器才会去找到这个类的字节码,加载、链接、初始化它到内存里。如果只是写了import但完全没用到这个类,那这个类的字节码连碰都不会碰,更不会占内存。
Python的import内存加载逻辑
Python的import就完全是另一回事了——它是执行期的执行语句,不是单纯的引用声明。当解释器执行到import module这一行的时候,会立刻去找到这个模块的文件,把整个模块的代码从头到尾执行一遍,然后把模块里所有的函数、类、变量、对象都加载到内存里,哪怕你之后一行都不用这个模块里的东西,它也已经占着内存了。
哪怕你用from module import func这种写法,本质上也是先把整个module全加载到内存,再把func这个符号导入到当前命名空间——模块本身还是完整加载了,只是你只拿到了部分引用而已,内存占用没减少。
你的假设场景对比
回到你最后那个假设:如果Java和Python程序都导入了3个同样大小的包,但只用到1个,那Python的内存占用会更高。因为Python已经把3个包的所有内容都加载进内存了,而Java只会加载那个被实际用到的包,另外两个包的类根本不会被JVM加载,完全不占用运行时内存。
备注:内容来源于stack exchange,提问作者Gautam Sahni

