diff --git a/mirai-core-api/src/commonMain/kotlin/message/data/Image.kt b/mirai-core-api/src/commonMain/kotlin/message/data/Image.kt
index e4b03a0cc..af56223ae 100644
--- a/mirai-core-api/src/commonMain/kotlin/message/data/Image.kt
+++ b/mirai-core-api/src/commonMain/kotlin/message/data/Image.kt
@@ -13,10 +13,7 @@
 @file:Suppress(
     "EXPERIMENTAL_API_USAGE",
     "unused",
-    "WRONG_MODIFIER_CONTAINING_DECLARATION",
-    "DEPRECATION",
     "UnusedImport",
-    "EXPOSED_SUPER_CLASS",
     "DEPRECATION_ERROR", "NOTHING_TO_INLINE"
 )
 
@@ -36,6 +33,8 @@ import net.mamoe.mirai.Bot
 import net.mamoe.mirai.IMirai
 import net.mamoe.mirai.Mirai
 import net.mamoe.mirai.contact.Contact
+import net.mamoe.mirai.contact.Contact.Companion.sendImage
+import net.mamoe.mirai.contact.Contact.Companion.uploadImage
 import net.mamoe.mirai.message.code.CodableMessage
 import net.mamoe.mirai.message.data.Image.Key.FRIEND_IMAGE_ID_REGEX_1
 import net.mamoe.mirai.message.data.Image.Key.FRIEND_IMAGE_ID_REGEX_2
diff --git a/mirai-core-api/src/jvmTest/kotlin/event/EventChannelTest.kt b/mirai-core-api/src/jvmTest/kotlin/event/EventChannelTest.kt
index 80066afc0..75c1c8fff 100644
--- a/mirai-core-api/src/jvmTest/kotlin/event/EventChannelTest.kt
+++ b/mirai-core-api/src/jvmTest/kotlin/event/EventChannelTest.kt
@@ -16,6 +16,7 @@ import net.mamoe.mirai.event.events.MessageEvent
 import org.junit.jupiter.api.Test
 
 internal class EventChannelTest {
+    @Suppress("UNUSED_VARIABLE")
     @Test
     fun testVariance() {
         var global: EventChannel<Event> = GlobalEventChannel
diff --git a/mirai-core-api/src/jvmTest/kotlin/event/JvmMethodEventsTest.kt b/mirai-core-api/src/jvmTest/kotlin/event/JvmMethodEventsTest.kt
index 01096e051..2cf71b7f9 100644
--- a/mirai-core-api/src/jvmTest/kotlin/event/JvmMethodEventsTest.kt
+++ b/mirai-core-api/src/jvmTest/kotlin/event/JvmMethodEventsTest.kt
@@ -90,7 +90,7 @@ internal class JvmMethodEventsTest {
         }
 
         TestClass().run {
-            this.registerEvents()
+            this.globalEventChannel().registerListenerHost(this)
 
             runBlocking {
                 TestEvent().broadcast()
@@ -119,7 +119,7 @@ internal class JvmMethodEventsTest {
         }
 
         TestClass().run {
-            this.registerEvents()
+            this.globalEventChannel().registerListenerHost(this)
 
             runBlocking {
                 TestEvent().broadcast()
@@ -150,7 +150,7 @@ internal class JvmMethodEventsTest {
         }
 
         TestClass().run {
-            this.registerEvents()
+            this.globalEventChannel().registerListenerHost(this)
 
             runBlocking {
                 TestEvent().broadcast()
diff --git a/mirai-core-api/src/jvmTest/kotlin/event/JvmMethodEventsTestJava.kt b/mirai-core-api/src/jvmTest/kotlin/event/JvmMethodEventsTestJava.kt
index d374f098f..1a708adc4 100644
--- a/mirai-core-api/src/jvmTest/kotlin/event/JvmMethodEventsTestJava.kt
+++ b/mirai-core-api/src/jvmTest/kotlin/event/JvmMethodEventsTestJava.kt
@@ -40,7 +40,7 @@ internal class JvmMethodEventsTestJava : SimpleListenerHost() {
 
     @Test
     fun test() {
-        this.registerEvents()
+        this.globalEventChannel().registerListenerHost(this)
         TestEvent().__broadcastJava()
         assertEquals(3, called.get(), null)
     }
diff --git a/mirai-core-api/src/jvmTest/kotlin/event/SimpleListenerHostTestJava.kt b/mirai-core-api/src/jvmTest/kotlin/event/SimpleListenerHostTestJava.kt
index 3ed7be402..c5cb20d16 100644
--- a/mirai-core-api/src/jvmTest/kotlin/event/SimpleListenerHostTestJava.kt
+++ b/mirai-core-api/src/jvmTest/kotlin/event/SimpleListenerHostTestJava.kt
@@ -33,7 +33,7 @@ class SimpleListenerHostTestJava {
             }
         }
         val scope = CoroutineScope(EmptyCoroutineContext)
-        scope.registerEvents(host)
+        scope.globalEventChannel().registerListenerHost(host)
         object : AbstractEvent() {}.__broadcastJava()
         if (!called.get()) {
             throw AssertionError("JavaTest: SimpleListenerHost Failed.")
diff --git a/mirai-core/src/jvmTest/kotlin/JavaApiTests.java b/mirai-core/src/jvmTest/kotlin/JavaApiTests.java
index 78527aa76..b64361d71 100644
--- a/mirai-core/src/jvmTest/kotlin/JavaApiTests.java
+++ b/mirai-core/src/jvmTest/kotlin/JavaApiTests.java
@@ -10,33 +10,47 @@
 import kotlin.coroutines.CoroutineContext;
 import net.mamoe.mirai.Bot;
 import net.mamoe.mirai.BotFactory;
+import net.mamoe.mirai.contact.Contact;
+import net.mamoe.mirai.contact.Group;
 import net.mamoe.mirai.event.EventHandler;
 import net.mamoe.mirai.event.ListeningStatus;
 import net.mamoe.mirai.event.SimpleListenerHost;
 import net.mamoe.mirai.event.events.GroupMessageEvent;
 import net.mamoe.mirai.event.events.MessageEvent;
+import net.mamoe.mirai.message.data.Image;
+import net.mamoe.mirai.message.data.MessageChain;
+import net.mamoe.mirai.message.data.MessageSource;
+import net.mamoe.mirai.message.data.MessageUtils;
 import net.mamoe.mirai.utils.BotConfiguration;
+import net.mamoe.mirai.utils.ExternalResource;
 import org.jetbrains.annotations.NotNull;
 
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.RandomAccessFile;
+
 /**
  * 仅用来测试调用,不会被单元测试运行
  */
+@SuppressWarnings({"unused", "UnusedAssignment"})
 public class JavaApiTests {
-    public static void main(String[] args) {
-        Bot bot = BotFactory.INSTANCE.newBot(11, "", configuration -> {
-            configuration.fileBasedDeviceInfo();
-            configuration.setProtocol(BotConfiguration.MiraiProtocol.ANDROID_PHONE);
-        });
+    @NotNull
+    Bot bot;
 
+    public JavaApiTests(@NotNull Bot bot) {
+        this.bot = bot;
+    }
+
+    public void generalCalls() {
         bot.login();
 
         bot.getAsFriend().sendMessage("test"); // blocking bridge
         bot.getOtherClients().getOrFail(1).getBot();
+    }
 
-        bot.getEventChannel().subscribe(MessageEvent.class, event -> {
-
-            return ListeningStatus.LISTENING;
-        });
+    public void events() {
+        bot.getEventChannel().subscribe(MessageEvent.class, event -> ListeningStatus.LISTENING);
 
         bot.getEventChannel().subscribeAlways(GroupMessageEvent.class, event -> {
             Bot b = event.getBot();
@@ -58,4 +72,85 @@ public class JavaApiTests {
 
         bot.getEventChannel().registerListenerHost(slh);
     }
+
+    @NotNull
+    private <T> T magic() {
+        throw new RuntimeException();
+    }
+
+    @NotNull
+    MessageChain chain = magic();
+
+    @NotNull
+    Contact contact = magic();
+
+    public void messages() {
+
+        Image image = (Image) chain.stream().filter(Image.class::isInstance).findFirst().orElse(null);
+
+        assert image != null;
+
+        String url = Image.queryUrl(image);
+        Image.fromId("123");
+
+        MessageSource source = magic();
+
+        MessageUtils.getBot(source);
+        MessageUtils.calculateImageMd5(image);
+        MessageUtils.isContentEmpty(image);
+
+        MessageSource.quote(source);
+        MessageSource.quote(chain);
+
+        MessageSource.recall(source);
+    }
+
+    ExternalResource resource = magic();
+
+    public void externalResource() throws IOException {
+        resource.inputStream();
+
+
+        contact.uploadImage(resource); // base method
+
+
+        ExternalResource r;
+
+        r = ExternalResource.create((InputStream) magic()); // throws IOException
+        r = ExternalResource.create((File) magic());
+        r = ExternalResource.create((RandomAccessFile) magic());
+
+        ExternalResource.uploadAsImage(r, contact);  // returns Image
+
+        ExternalResource.sendAsImage(r, contact);    // returns MessageReceipt
+
+
+        ExternalResource.uploadAsImage((ExternalResource) magic(), contact);    // returns Image
+        ExternalResource.uploadAsImage((File) magic(), contact);                // returns Image
+        ExternalResource.uploadAsImage((InputStream) magic(), contact);         // returns Image
+
+        ExternalResource.sendAsImage((ExternalResource) magic(), contact);  // returns MessageReceipt
+        ExternalResource.sendAsImage((File) magic(), contact);              // returns MessageReceipt
+        ExternalResource.sendAsImage((InputStream) magic(), contact);       // returns MessageReceipt
+
+        Contact.uploadImage(contact, (ExternalResource) magic());   // returns Image
+        Contact.uploadImage(contact, (File) magic());               // returns Image
+        Contact.uploadImage(contact, (InputStream) magic());        // returns Image
+
+        Contact.sendImage(contact, (ExternalResource) magic());     // returns MessageReceipt
+        Contact.sendImage(contact, (File) magic());                 // returns MessageReceipt
+        Contact.sendImage(contact, (InputStream) magic());          // returns MessageReceipt
+
+        // experimental
+        ExternalResource.uploadAsGroupVoice(magic(), (Group) contact);
+    }
+
+    public static void main(String[] args) {
+        Bot bot = BotFactory.INSTANCE.newBot(11, "", configuration -> {
+            configuration.fileBasedDeviceInfo();
+            configuration.setProtocol(BotConfiguration.MiraiProtocol.ANDROID_PHONE);
+        });
+
+        new JavaApiTests(bot);
+    }
 }