Module
. Что-то вродеList<Module> discoverModules(File dir) {}
Module
). Здесь самый нетривиальный вопрос, как этот модуль найти внутри архива. Самый простой (для начала) способ - положить в каждый jar-файл по определенному пути некий конфиг, в котором указать путь к модулю. И такой конфиг в jar-файле уже есть - стандартный META-INF. В простейшем случае у нас получается jar-файл из двух файлов с такой структурой:MyMod.jar
├───META-INF
│ └───MANIFEST.MF
└───mymod
└───MyMod.class
MANIFEST.MF
содержит строчкуMain-Class: mymod.MyMod
Module
. Содержимое MyMod.javapackage mymod;
public class MyMod implements Module {
public int run() {
System.out.println("MyMod loaded!");
}
}
public class ModuleLoader {
public static void main(String[] args) {
List<Module> mods = new ModuleLoader().discoverModules(new File("/modules"));
for(Module mod : mods)
mod.run();
}
public List<Module> discoverModules(File dir) {
List<File> jarFiles = Stream.of(dir.listFiles())
.filter(f -> f.getName().endsWith(".jar"))
.collect(Collectors.toList());
URL[] moduleUrls = jarFiles.stream().map(this::toUrl).toArray(URL[]::new);
URLClassLoader classLoader = new URLClassLoader(moduleUrls, getClass().getClassLoader());
return jarFiles.stream()
.map(this::getMainClassName)
.map(name -> {
try {
return (Module) classLoader.loadClass(name).newInstance();
} catch(Exception e) {
throw new RuntimeException(e);
}
})
.collect(Collectors.toList());
}
private String getMainClassName(File file) {
try(JarFile jar = new JarFile(file)){
return (String) jar.getManifest().getMainAttributes().get("Main-Class");
} catch(IOException e) {
throw new RuntimeException(e);
}
}
private URL toUrl(File file) {
try {
return file.toURI().toURL();
} catch(MalformedURLException e) {
throw new RuntimeException(e);
}
}
}
<Loggers>
<Root level="ERROR">
<AppenderRef ref="CONSOLE" />
<AppenderRef ref="MYSQL" />
</Root>
</Loggers>
public class Waiter {
private static volatile boolean isWaiting;
public static void start() {
if(isWaiting) throw new IllegalStateException();
isWaiting = true;
System.out.print("Жду .");
new Thread(() -> {
for(int i = 1; isWaiting; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException ignored) {}
System.out.print(i % 3 == 0 ? "\b\b" : ".");
}
System.out.println();
}).start();
}
public static void stop() {
if(!isWaiting) throw new IllegalStateException();
isWaiting = false;
}
}
import sun.misc.Unsafe;
public class CrashTheJVM
{
private static final Unsafe UNSAFE = createUnsafe();
private static Unsafe createUnsafe()
{
try
{
Field uf = Unsafe.class.getDeclaredField("theUnsafe");
uf.setAccessible(true);
return (Unsafe) uf.get(null);
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
public static void main(String[] args)
{
UNSAFE.getByte(0);
}
}
getClass().getProtectionDomain().getCodeSource().getLocation();
((java.net.URLClassLoader)getClass().getClassLoader()).getURLs();
public class SomeStruct {
public int i1;
public int i2;
public void writeTo(DataOutputStream data) {
data.writeInt(i1);
data.writeInt(i2);
}
public void readFrom(DataInputStream data) {
i1 = data.readInt();
i2 = data.readInt();
}
}
Integer.reverseBytes(i1);
Cipher.getInstance("AES/CTR/PKCS5Padding");