我对JAVA有些怀疑。 我有一个任务执行器,它将为每个任务创建一个新线程,每个线程将从jar执行一个任务
Runtime.getRuntime().exec(" java -jar myjar");
我在一些帖子中读到,通过这样执行,每个线程都会创建自己的JVM。然后,如果我想使用两个线程从同一个jar执行相同的类或不同的类,它将在两个JVM中创建相同jar的副本。实际上我想避免在两个JVM中复制相同的jar。而不是我想在多个JVM之间共享相同的jar。
请提供一些有关此情况的提示。
答案 0 :(得分:1)
JVM不需要自己的jar副本。它只需要在类路径中找到它。同一个jar可以在几个运行的java程序的类路径中。
当然,每个JVM都有自己的内存,其类路径中来自jar的类将被加载到每个JVM的内存中。为两个不同JVM加载的类共享相同的内存是不可能的。如果要共享内存,请不要使用多个Java进程,而是使用线程。
答案 1 :(得分:0)
你并不是真的“将jar复制”到JVM中。您正在从中加载类,并且只加载所需的类。现在,除非你以某种方式设法获得大量MiB的几个类文件,并产生了数十个这样的过程,这应该不是什么大问题。让每个JVM进程处理自己的问题并保持简单,你会好得多。在运行多个JVM时,您很有可能在后台进行一些优化。不要再猜测实现优化。
如果由于某种原因这确实是一个绝对的要求,那么你将陷入困境。我能想到的唯一解决方案是编写一个以某种方式使用共享内存的自定义类加载器。这很可能涉及使用Java Native Interface,迫使您编写特定于平台的代码。也许那里有一些可用的解决方案,但我知道没有这样的事情。
这就是假设你应该首先产生其他Java进程。我认为你最好不要考虑让这些其他进程在不同的线程中运行,而不是在同一个Java进程中运行。 Java并发工具(在包java.util.concurrent
中)使这些事情变得更易于管理。
HotSpot JVM本身在系统jar文件上使用class data sharing来减少内存占用并加速多个JVM的引导。也许源代码可以提供一些想法。但我认为这绝对是尝试解决你遇到的任何问题的最后一件事。除非您遇到严重的内存问题,并且真的需要多个进程,否则您正在尝试优化您应该远离的内容。
答案 2 :(得分:0)
(你当然可以有两个JVM共享一个JAR文件,这不会“创建一个JAR文件的副本”......但我不认为这是你的问题的真正含义。)
Sun / Oracle Java有一个名为CDS的功能(在Java 5.0中引入),允许从“rt.jar”加载的类在多个JVM实例之间共享。编译后的类被保存到称为“共享归档”的东西,然后可以将内存映射到多个JVM的地址空间......以加速JVM启动。但是,CDS不适用于应用程序类。
显然,IBM的Java 5实现有一个类似于"Shared Classes"的功能,它也适用于应用程序类。
您可以通过这种方式保存一些内存,但不清楚您是否会节省大量内存。如果您真的关心内存使用和JVM启动时间,那么最好在父JVM中运行子Java应用程序。 (当然,缺点是,如果任何一个子Java应用程序行为不当,它可能导致只能通过退出父JVM解决的问题。)