環境資訊中心綜合外電;姜唯 編譯;林大利 審校
本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計
※不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務
※Google地圖已可更新顯示潭子電動車充電站設置地點!!
面對“2020年二氧化碳排放95克/公里”的嚴苛法規,歐洲車企將在未來幾年密集發佈純電動車、插電式混合動力車。此環境下,奧迪也在積極部署電動車發展規劃。
2016年奧迪A6 e-tron在中國生產 在電動車市場上,隨著中國政府政策激勵,各地建設充電樁、充電站將出現高潮,購買使用電動車的門檻降低,促進新能源車市場加快發展。 奧迪管理董事會主席施泰德在2015年法蘭克福車展上透露,奧迪A6 e-tron以及其使用的鋰離子電池將於2016年啟動中國生產。據悉,這款新能源車由中德工程團隊聯合研發,並針對中國的市場需求、使用工況進行改進。
2020年後,奧迪新能源車占市場15%-20%份額 施泰德判斷,2020年後,純電動車、插電混合動力車會出現發展的高峰期,奧迪旗下的新能源產品有望實現15%-20%的市場份額。 在中國的消費結構上,豪華車市場仍在正面、快速地發展,豪華車的消費占比會突破12%,甚至有望達到15%。動力電池技術日趨成熟,e-tron quattro已經實現500公里的續航里程,中國產奧迪A6 e-tron導入最新的動力電池技術、能量管理方案以提升產品的競爭力。
本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計
※不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務
※Google地圖已可更新顯示潭子電動車充電站設置地點!!
鴻海集團電動車布局邁入最後衝刺階段,市場傳出,鴻海旗下富士康與騰訊、和諧汽車在大陸鄭州合資的電動車計畫,工廠將在 2018 年開始大量量產,並將結合鴻準、群創、 F-乙盛等「鴻家軍」成員,搶食大陸市場電動車商機。 鴻海、騰訊與和諧是在今年 6 月共同宣布在鄭州成立合資公司「和諧富騰」,搶進電動車市場。市場人士認為,這三方合作,各取自家集團單字做為公司名稱的「和諧富騰」,預料將結合現今物聯網新趨勢,打造與眾不同的智慧電動小客車。「和諧富騰」初期資本額人民幣 10 億元(約新台幣 50 億元),由和諧持股 40%、鴻海 30%、深圳騰訊 30%。 最新消息傳出,「和諧富騰」的工廠有望明、後年完工,2018 年量產,主打中高階市場,有望成為「電動車界的蘋果」,以精品概念搶市。市場認為,這三方合作的「鑽石組合」,將由鴻海負責拿手的電子相關設備生產,騰訊運用其在互聯網產業的平台,配合和諧在金字塔頂端、豪華汽車經銷商的服務利基,具有非常大的競爭優勢。
本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計
※不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務
※Google地圖已可更新顯示潭子電動車充電站設置地點!!
目錄
在和其他廠商對接的時候,經常會將某數據庫的某些表放開增刪改查(CRUD)的權限給對方,此時,就要新建個用戶,授予某數據庫的某些表CRUD的權限;還有的時候只需授權SELECT權限,其他權限不能授予;
演示所用數據庫版本:SQL Server Management Studio V17.8.1
數據庫TestDB中已經有兩個表,分別為User和Salary,現在對錶User進行權限設置,將Insert、update、delete、select的權限賦給用戶【zyl】;
1)、表上右鍵選擇【屬性】,選擇【權限】選項卡:
2)、點擊【搜索】,在彈出的框中點擊【瀏覽】,選擇需要設置的用戶;
3)、在上面點擊【確定】后,就可以在【權限】選項卡中看到權限列表,選擇需要的權限點擊確定即可;
4)、當選中【選擇】和【引用】權限時,還可以設置【列權限】;
並且用戶【zyl】只能對錶User進行增刪改查,不能修改表結構;
如果設置了【列權限】,沒有選擇【設置】權限,那麼select * 就會報錯;
在數據庫的【安全性】-【用戶】-【zyl】-【屬性】-【安全對象】;
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計
※不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務
※Google地圖已可更新顯示潭子電動車充電站設置地點!!
摘錄自2020年1月16日中央社報導
台灣的太平洋友邦馬紹爾群島是受氣候變遷威脅最大的國家之一,前總統海妮受訪時不僅表示遺憾有些國家未嚴肅看待氣候議題,還提到執政時曾接受台灣援助促進女權。
路透社報導,在海拔低的馬紹爾群島,全球暖化造成海平面緩慢升高,連卸任總統海妮(Hilda Heine)都必須在她樸素的家裡處理漫入花園的鹹海水。她說,「情況一年比一年糟」。
馬紹爾群島由超過30個熱帶珊瑚環礁組成,其中多數環礁的平均海拔僅約兩公尺。海妮受訪時說:「全世界都在談氣候變遷,對我們而言,這是攸關存亡的威脅,我們已經盡力把這項議題搬上國際場域了。」
過去四年,馬紹爾群島發布八次衛生緊急狀態,包括透過蚊子傳染的登革熱、茲卡病毒、屈公病疫情爆發,海妮認為這都與氣候變遷有關。
本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計
※不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務
※Google地圖已可更新顯示潭子電動車充電站設置地點!!
近日,特斯拉中國公共策劃與充電基礎設施總監高翔在接受記者採訪時表示,“充電並不是一件很難的事情“,甚至以後可以“把電賣給電網“。
電動汽車充電並不難
目前,對比汽油車加油,電動車充電仍然給人們一種“充電還是很困難“的感覺。高翔對此解釋道,汽油車發展超過100年了,剛開始也是很困難,但是現在到處都有加油站,我們也覺得很方便。而事實上,充電並沒有我們想像中那麼難,舉例來說,電動車充電並不需要像加油站那樣大的土地,也不需要擔憂運輸、儲油的安全性問題。
據悉,目前特斯拉汽車的充電方式有三種:一是家庭充電,充電設備隨車贈送;二是建在各大商場、酒店、旅遊地的“目的地充電樁”,方便車主外出時充電。跟家電充電一樣,目的地充電樁同樣是支援220V電壓,所以充電時間較長,充滿一次需要11.5-13小時左右;三是超級充電站。由於其配備的超級充電器是通過特製電纜繞過車載充電設備,直接將380V的直流電輸入電池,所以充電時間大為縮短。目的地充電樁每充電1小時可行駛至少50公里,而使用超級充電站,20分鐘就能充滿一半,80分鐘即可完全充滿,並可行駛400公里以上。並且車主在此可以免費充電。
電動車發展明年將會進入爆發式增長
為什麼大家對發展電動汽車有很深的理解,一個是霧霾,近幾年日益嚴重;另外一個是能源危機,我們採用的化石能源60%左右依賴於進口。在能源危機和環境壓力面前,我們需要很好的解決方案。而在出行方式裡面,汽油車占到90%的汽油消耗量,所以電動汽車對這方面有很大的幫助。
同時,國家新的標準馬上也要發佈,高翔預測,整個電動車行業到2016年將會進入一個爆發式增長,甚至在以後,國家除了對車進行補貼外,也將會對基礎設施進行支持,大力推進基礎設施充電的發展。有了這些,剩下的就是企業把車做好。未來充電市場和電動車行業一定是相輔相成的。
把車裡的電賣給電網
電動汽車行業與電網本來就是天然的合作關係。電動汽車除了把電能作為能源之外,其實也是能源互聯網以及智慧電網中的一個環節。據高翔介紹,電網作為一個承擔著中國電力行業社會責任的企業,對於電動汽車的發展一直都是支援的,特別是北上廣深等大城市,在這方面有著非常清晰的政策。
而從長遠來看,電動汽車的發展對電網來說也是一個好事。充電設施多了,對電網企業了來說,最重要的絕不是“充個電、收個服務費“,而是未來發展智慧電網、甚至是發展車和電網的互聯互通。比如說VTOG(雙向逆變充放電技術),從車反過來給電網充電,充好電的車相當於無數個儲能電池,對電網起到削峰填穀的作用,也就是說,晚上用不掉的電儲存到車裡來,白天用電高峰時候電動汽車用戶再把這些電散落地賣還給電網。
高翔解釋道,現在電網發電還做不到即時的調控,要滿足高峰用電,就需要按照需求最大值來發電,但是電網大多數時間是用不了這麼多電的,晚上好多電用不掉但是也不能停,否則經濟損失很大。如果採取了上面這種做法的話,不但車主能得到收益,電網也能節省很大的發電及儲能成本,將是一個非常理想的削峰填穀模式。
本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計
※不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務
※Google地圖已可更新顯示潭子電動車充電站設置地點!!
喜歡可以點個贊哦
程序計數器
Java虛擬機棧
本地方法棧
Java堆(GC區)(Java Head)
JDK1.7 方法區(永久代)
運行時常量池
JDK1.8 元空間
直接內存
句柄訪問
直接指針訪問(HotSpot使用)
第一次標記(緩刑)
引用計數算法
但是它難以解決對象之間的相互循環引用的情況,此時這個兩個對象引用計數值為1,但是永遠無法用到這兩個對象。
- 可達性分析算法(Java使用)
- 以一系列GC Roots的對象作為起始點,從這些節點開始向下搜索,搜索所走過的路徑稱為引用鏈,當一個對象到GC Roots沒有任何引用鏈相連是,則證明此對象不可用,可以被回收。
GC Roots對象包括
第二次標記
finalize()
滿足無用的類三個判斷條件才僅僅代表可以進行回收,不是必然關係,可以使用-Xnoclassgc參數控制。
不足:
現在商業虛擬機都採用這種算法用於新生代。
因為新生代中的對象98%都是朝生暮死,所以將內存分為一塊較大的Eden空間和兩塊較小的Survivor空間,每次使用Eden和其中一塊Survivor空間。
當回收時,如果另外一塊Survivor空間沒有足夠的空間存放存活下來的對象時,這些對象將直接通過分配擔保機制進入老年代。
枚舉根節點(GC Roots)
安全點
程序執行只有到達安全點時才能暫停,到達安全點有兩種方案。
但是當線程sleep或blocked時無法響應JVM的中斷請求走到安全點中斷掛起,所以引出安全區域。
安全區域
線程進入安全區域時表示自己進入了安全區域,這個發生GC時,JVM就不需要管這個線程。
線程離開安全區域時,檢查系統是否完成GC過程,沒有就等待可以離開安全區域的信號為止,否者繼續執行。
新生代
優點:對比其他單線程收集器簡單高效,對於單個CPU環境來說,沒有線程交互的開銷,因此擁有最高的單線程收集效率。
它是Client場景下默認新生代收集器,因為在該場景下內存一般來說不會很大。
- 2. parnew收集器
- 它是Serial收集器的多線程版本,公用了相當多的代碼。
在單CPU環境中絕對不會有比Serial收集器更好的效果,甚至在2個CPU環境中也不能百分之百超越。
它是Server場景下默認的新生代收集器,主要因為除了Serial收集器,只用它能與CMS收集器配合使用。
- 3. parallel scavenge收集器
- “吞吐優先”收集器,與ParNew收集器差不多。
但是其他收集器的目標是盡可能縮短垃圾收集時用戶線程停頓的時間,而它的目標是達到一個可控制的吞吐量。這裏的吞吐量指CPU用於運行用戶程序的時間佔總時間的比值。
老年代
也是給Client場景下的虛擬機使用的。
- 5. parallel old收集器
- 是Parallel Scavenge收集器的老年代版本。
在注重吞吐量已經CPU資源敏感的場合,都可以優先考慮Parallel Scavenge和Parallel Old收集器。
- 6. cms收集器
- Concurrent Mark Sweep收集器是一種以獲取最短回收停頓時間為目標的收集器。
- 運作過程
- 1. 初始標記(最短)。仍需要暫停用戶線程。只是標記一下GC Roots能直接關聯到的對象,速度很快
1 和4 兩個步驟並沒有帶上併發兩個字,即這兩個步驟仍要暫停用戶線程。
- 優缺點
- 併發收集、低停頓。
運作過程
主動引用
被動引用
初始化階段才真正執行類中定義的Java程序代碼,是執行類構造器 ()方法的過程。
在準備階段,類變量已經給過零值,而在初始化階段,根據程序員通過程序制定的主觀計劃去初始化類變量和其他資源。
()
虛擬機會保證clinit在多線程環境中被正確的加鎖、同步。其他線性喚醒之後不會再進入clinit方法,同一個類加載器下,一個類型只會初始化一次。
- <init>()
- 對象構造器方法。Java對象被創建時才會進行實例化操作,對非靜態變量解析初始化。
會顯式的調用父類的init方法,對象實例化過程中對實例域的初始化操作全部在init方法中進行。
類與類加載器
類加載器分類
啟動類加載器
擴展類加載器
應用程序類加載器
自定義類加載器
雙親委派模型
工作過程
好處
Minor GC
時機
Full GC
時機
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計
※不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務
※Google地圖已可更新顯示潭子電動車充電站設置地點!!
編者注:Netty是Java領域有名的開源網絡庫,特點是高性能和高擴展性,因此很多流行的框架都是基於它來構建的,比如我們熟知的Dubbo、Rocketmq、Hadoop等。本文就netty線程模型展開分析討論下 : )
IO模型
NIO和AIO不同之處在於應用是否進行真正的讀寫操作。
reactor和proactor模型
netty的線程模型是基於Reactor模型的。
Reactor 單線程模型,是指所有的 I/O 操作都在同一個 NIO 線程上面完成的,此時NIO線程職責包括:接收新建連接請求、讀寫操作等。
在一些小容量應用場景下,可以使用單線程模型(注意,Redis的請求處理也是單線程模型,為什麼Redis的性能會如此之高呢?因為Redis的讀寫操作基本都是內存操作,並且Redis協議比較簡潔,序列化/反序列化耗費性能更低
)。但是對於高負載、大併發的應用場景卻不合適,主要原因如下:
Rector 多線程模型與單線程模型最大的區別就是有一組 NIO 線程來處理連接讀寫操作,一個NIO線程處理Accept。一個NIO線程可以處理多個連接事件,一個連接的事件只能屬於一個NIO線程。
在絕大多數場景下,Reactor 多線程模型可以滿足性能需求。但是,在個別特殊場景中,一個 NIO 線程負責監聽和處理所有的客戶端連接可能會存在性能問題。例如併發百萬客戶端連接,或者服務端需要對客戶端握手進行安全認證,但是認證本身非常損耗性能。在這類場景下,單獨一個 Acceptor 線程可能會存在性能不足的問題,為了解決性能問題,產生了第三種 Reactor 線程模型——主從Reactor 多線程模型。
主從 Reactor 線程模型的特點是:服務端用於接收客戶端連接的不再是一個單獨的 NIO 線程,而是一個獨立的 NIO 線程池。Acceptor 接收到客戶端 TCP連接請求並處理完成后(可能包含接入認證等),將新創建的 SocketChannel注 冊 到 I/O 線 程 池(sub reactor 線 程 池)的某個I/O線程上, 由它負責SocketChannel 的讀寫和編解碼工作。Acceptor 線程池僅僅用於客戶端的登錄、握手和安全認證,一旦鏈路建立成功,就將鏈路註冊到後端 subReactor 線程池的 I/O 線程上,由 I/O 線程負責後續的 I/O 操作。
netty 的線程模型並不是一成不變的,它實際取決於用戶的啟動參數配置。通過設置不同的啟動參數,Netty 可以同時支持 Reactor 單線程模型、多線程模型。
為了盡可能地提升性能,Netty 在很多地方進行了無鎖化的設計,例如在 I/O 線程內部進行串行操作,避免多線程競爭導致的性能下降問題。表面上看,串行化設計似乎 CPU 利用率不高,併發程度不夠。但是,通過調整 NIO 線程池的線程參數,可以同時啟動多個串行化的線程并行運行,這種局部無鎖化的串行線程設計相比一個隊列多個工作線程的模型性能更優。(小夥伴們後續多線程併發流程可參考該類實現方案
)
Netty 的 NioEventLoop 讀取到消息之後,直接調用 ChannelPipeline 的fireChannelRead (Object msg)
。 只要用戶不主動切換線程, 一直都是由NioEventLoop 調用用戶的 ChannelHandler,期間不進行線程切換。這種串行化處理方式避免了多線程操作導致的鎖的競爭,從性能角度看是最優的。
Netty擁有兩個NIO線程池,分別是bossGroup
和workerGroup
,前者處理新建連接請求,然後將新建立的連接輪詢交給workerGroup中的其中一個NioEventLoop來處理,後續該連接上的讀寫操作都是由同一個NioEventLoop來處理。注意,雖然bossGroup也能指定多個NioEventLoop(一個NioEventLoop對應一個線程),但是默認情況下只會有一個線程,因為一般情況下應用程序只會使用一個對外監聽端口。
這裏試想一下,難道不能使用多線程來監聽同一個對外端口么,即多線程epoll_wait到同一個epoll實例上?
epoll相關的主要兩個方法是epoll_wait和epoll_ctl,多線程同時操作同一個epoll實例,那麼首先需要確認epoll相關方法是否線程安全:簡單來說,epoll是通過鎖來保證線程安全的, epoll中粒度最小的自旋鎖ep->lock(spinlock)用來保護就緒的隊列, 互斥鎖ep->mtx用來保護epoll的重要數據結構紅黑樹。
看到這裏,可能有的小夥伴想到了Nginx多進程針對監聽端口的處理策略,Nginx是通過accept_mutex機制來保證的。accept_mutex是nginx的(新建連接)負載均衡鎖,讓多個worker進程輪流處理與client的新連接。當某個worker進程的連接數達到worker_connections配置(單個worker進程的最大處理連接數)的最大連接數的7/8時,會大大減小獲取該worker獲取accept鎖的概率,以此實現各worker進程間的連接數的負載均衡。accept鎖默認打開,關閉它時nginx處理新建連接耗時會更短,但是worker進程之間可能連接不均衡,並且存在“驚群”問題。只有在使能accept_mutex並且當前系統不支持原子鎖時,才會用文件實現accept鎖。注意,accept_mutex加鎖失敗時不會阻塞當前線程,類似tryLock。
現代linux中,多個socker同時監聽同一個端口也是可行的,nginx 1.9.1也支持這一行為。linux 3.9以上內核支持SO_REUSEPORT選項,允許多個socker bind/listen在同一端口上。這樣,多個進程可以各自申請socker監聽同一端口,當連接事件來臨時,內核做負載均衡,喚醒監聽的其中一個進程來處理,reuseport機制有效的解決了epoll驚群問題。
再回到剛才提出的問題,java中多線程來監聽同一個對外端口,epoll方法是線程安全的,這樣就可以使用使用多線程監聽epoll_wait了么,當然是不建議這樣乾的,除了epoll的驚群問題之外,還有一個就是,一般開發中我們使用epoll設置的是LT模式(水平觸發方式,與之相對的是ET默認,前者只要連接事件未被處理就會在epoll_wait時始終觸發,後者只會在真正有事件來時在epoll_wait觸發一次
),這樣的話,多線程epoll_wait時就會導致第一個線程epoll_wait之後還未處理完畢已發生的事件時,第二個線程也會epoll_wait返回,顯然這不是我們想要的,關於java nio的測試demo如下:
public class NioDemo {
private static AtomicBoolean flag = new AtomicBoolean(true);
public static void main(String[] args) throws Exception {
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.socket().bind(new InetSocketAddress(8080));
// non-block io
serverChannel.configureBlocking(false);
Selector selector = Selector.open();
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
// 多線程執行
Runnable task = () -> {
try {
while (true) {
if (selector.select(0) == 0) {
System.out.println("selector.select loop... " + Thread.currentThread().getName());
Thread.sleep(1);
continue;
}
if (flag.compareAndSet(true, false)) {
System.out.println(Thread.currentThread().getName() + " over");
return;
}
Iterator<SelectionKey> iter = selector.selectedKeys().iterator();
while (iter.hasNext()) {
SelectionKey key = iter.next();
// accept event
if (key.isAcceptable()) {
handlerAccept(selector, key);
}
// socket event
if (key.isReadable()) {
handlerRead(key);
}
/**
* Selector不會自己從已選擇鍵集中移除SelectionKey實例,必須在處理完通道時手動移除。
* 下次該通道變成就緒時,Selector會再次將其放入已選擇鍵集中。
*/
iter.remove();
}
}
} catch (Exception e) {
e.printStackTrace();
}
};
List<Thread> threadList = new ArrayList<>();
for (int i = 0; i < 2; i++) {
Thread thread = new Thread(task);
threadList.add(thread);
thread.start();
}
for (Thread thread : threadList) {
thread.join();
}
System.out.println("main end");
}
static void handlerAccept(Selector selector, SelectionKey key) throws Exception {
System.out.println("coming a new client... " + Thread.currentThread().getName());
Thread.sleep(10000);
SocketChannel channel = ((ServerSocketChannel) key.channel()).accept();
channel.configureBlocking(false);
channel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));
}
static void handlerRead(SelectionKey key) throws Exception {
SocketChannel channel = (SocketChannel) key.channel();
ByteBuffer buffer = (ByteBuffer) key.attachment();
buffer.clear();
int num = channel.read(buffer);
if (num <= 0) {
// error or fin
System.out.println("close " + channel.getRemoteAddress());
channel.close();
} else {
buffer.flip();
String recv = Charset.forName("UTF-8").newDecoder().decode(buffer).toString();
System.out.println("recv: " + recv);
buffer = ByteBuffer.wrap(("server: " + recv).getBytes());
channel.write(buffer);
}
}
}
(1) 時間可控的簡單業務直接在 I/O 線程上處理
時間可控的簡單業務直接在 I/O 線程上處理,如果業務非常簡單,執行時間非常短,不需要與外部網絡交互、訪問數據庫和磁盤,不需要等待其它資源,則建議直接在業務 ChannelHandler 中執行,不需要再啟業務的線程或者線程池。避免線程上下文切換,也不存在線程併發問題。
(2) 複雜和時間不可控業務建議投遞到後端業務線程池統一處理
複雜度較高或者時間不可控業務建議投遞到後端業務線程池統一處理,對於此類業務,不建議直接在業務 ChannelHandler 中啟動線程或者線程池處理,建議將不同的業務統一封裝成 Task,統一投遞到後端的業務線程池中進行處理。過多的業務ChannelHandler 會帶來開發效率和可維護性問題,不要把 Netty 當作業務容器,對於大多數複雜的業務產品,仍然需要集成或者開發自己的業務容器,做好和Netty 的架構分層。
(3) 業務線程避免直接操作 ChannelHandler
業務線程避免直接操作 ChannelHandler,對於 ChannelHandler,IO 線程和業務線程都可能會操作,因為業務通常是多線程模型,這樣就會存在多線程操作ChannelHandler。為了盡量避免多線程併發問題,建議按照 Netty 自身的做法,通過將操作封裝成獨立的 Task 由 NioEventLoop 統一執行,而不是業務線程直接操作,相關代碼如下所示:
如果你確認併發訪問的數據或者併發操作是安全的,則無需多此一舉,這個需要根據具體的業務場景進行判斷,靈活處理。
推薦閱讀
歡迎小夥伴關注【TopCoder】閱讀更多精彩好文。
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計
※不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務
※Google地圖已可更新顯示潭子電動車充電站設置地點!!
2015年12月28日,北京汽車集團有限公司就“北汽新能源汽車動力電池”、“北汽集團常州產業基地”兩個專案,與常州市政府簽約。
此次北汽集團擬在常州建設的兩個項目總投資80億元,其中,北汽新能源汽車動力電池專案總投資約30億元,規劃動力電池產能達到5G瓦時,同時將以滆湖低碳濕地公園培訓中心為主體,打造北汽新能源綠色商學院,其主要目的是加強新體系電池基礎研究和關鍵技術開發,推進新一代鋰離子電池的工程化和產業化,實現對動力電池產業鏈核心環節資源掌控,以支撐北汽新能源業務需求。
而北汽集團常州產業基地專案總投資50億元,總規劃年產30萬輛整車及配套零部件、物流專案,其中一期年產15萬輛SUV、MPV和輕型客車,二期重點生產新能源汽車,打造產業生態鏈。
此前,北汽集團總投資100億元的新能源汽車和總投資50億元的通用航空兩個項目已經於今年4月和10月相繼落戶常州。
本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計
※不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務
※Google地圖已可更新顯示潭子電動車充電站設置地點!!
今天繼續講述逆向開發中另一個比較重要的課程是代碼注入內容,本篇篇幅比較長,但還是有很多乾貨的,希望大家通過此篇文章更加了解逆向開發中的要點和知識點.我們將分解幾個內容,進行講解:
讓代碼執行自己的代碼,整體方案如下:
如何讓別人的app來執行自己的代碼呢? 這就要通過代碼注入的方式來達到,而代碼注入的方式有兩種: 一種是通過framework, 一種是dylib方式,另種方案,可以通過Runtime機制
代碼注入思路:
DYLD會動態加載動態庫Framework中所有動態庫,在frameworks中加入自己的一個動態庫,然後在動態庫中hook和注入代碼.
MachOView的下載地址:
如果想看源碼如下:MachOView源碼:
yololib工具下載地址:
我們看到有很多的DYLIB,代表的是加載動態庫
由上可知,WJHookFrameWork已經加入成功。
原因:用MachOView打開可執行的WeChat,沒有找到WJHookFrameWork
下面我們講述怎麼將WJHookFramework寫入到MachoView文件中?
需要使用yololib工具,建議將yololib放到 /usr/local/bin
需要增加執行權限: chmod +x WeChat
yololib WeChat Frameworks/WJHookFrameWork.framework/WJHookFrameWork
通過上面的過程,查看MachOView文件Load commands中是否有WJHookFrameWork
上面圖显示已經加入成功。
zip -ry WeChat.ipa Payload
將WeChat.ipa放入App目錄中,刪除其他的文件夾。
上面就是framework方式代碼注入。大家可以私信我,如有不懂!!!
加入腳本文件
# ${SRCROOT} 它是工程文件所在的目錄 TEMP_PATH="${SRCROOT}/Temp" #資源文件夾,我們提前在工程目錄下新建一個APP文件夾,裏面放ipa包 ASSETS_PATH="${SRCROOT}/APP" #目標ipa包路徑 TARGET_IPA_PATH="${ASSETS_PATH}/*.ipa" #清空Temp文件夾 rm -rf "${SRCROOT}/Temp" mkdir -p "${SRCROOT}/Temp" #---------------------------------------- # 1. 解壓IPA到Temp下 unzip -oqq "$TARGET_IPA_PATH" -d "$TEMP_PATH" # 拿到解壓的臨時的APP的路徑 TEMP_APP_PATH=$(set -- "$TEMP_PATH/Payload/"*.app;echo "$1") # echo "路徑是:$TEMP_APP_PATH" #---------------------------------------- # 2. 將解壓出來的.app拷貝進入工程下 # BUILT_PRODUCTS_DIR 工程生成的APP包的路徑 # TARGET_NAME target名稱 TARGET_APP_PATH="$BUILT_PRODUCTS_DIR/$TARGET_NAME.app" echo "app路徑:$TARGET_APP_PATH" rm -rf "$TARGET_APP_PATH" mkdir -p "$TARGET_APP_PATH" cp -rf "$TEMP_APP_PATH/" "$TARGET_APP_PATH" #---------------------------------------- # 3. 刪除extension和WatchAPP.個人證書沒法簽名Extention rm -rf "$TARGET_APP_PATH/PlugIns" rm -rf "$TARGET_APP_PATH/Watch" #---------------------------------------- # 4. 更新info.plist文件 CFBundleIdentifier # 設置:"Set : KEY Value" "目標文件路徑" /usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $PRODUCT_BUNDLE_IDENTIFIER" "$TARGET_APP_PATH/Info.plist" #---------------------------------------- # 5. 給MachO文件上執行權限 # 拿到MachO文件的路徑 APP_BINARY=`plutil -convert xml1 -o - $TARGET_APP_PATH/Info.plist|grep -A1 Exec|tail -n1|cut -f2 -d\>|cut -f1 -d\<` #上可執行權限 chmod +x "$TARGET_APP_PATH/$APP_BINARY" #---------------------------------------- # 6. 重簽名第三方 FrameWorks TARGET_APP_FRAMEWORKS_PATH="$TARGET_APP_PATH/Frameworks" if [ -d "$TARGET_APP_FRAMEWORKS_PATH" ]; then for FRAMEWORK in "$TARGET_APP_FRAMEWORKS_PATH/"* do #簽名 /usr/bin/codesign --force --sign "$EXPANDED_CODE_SIGN_IDENTITY" "$FRAMEWORK" done fi #注入 yololib "$TARGET_APP_PATH/$APP_BINARY" "Frameworks/libHankHook.dylib"
上面就是dylib方式代碼注入,希望對大家有所幫助!!!
通過上面的兩種方式實現代碼注入,讓別人的app運行自己的app,下面總結如下:
iOS 中實現AOP編程思想的方式其中之一是Method Swizzling,而 Method Swizzling 是利用Runtime特性把一個方法和另個方法的實現做替換,程序運行時修改Dispatch Table里SEL和IMP之間的映射關係.
通過swizzling method改變目標函數selector所指向實現,在新的實現中來實現所要改的內容即可.
@implementation NSURL (HKURL) +(void)load { Method URLWithStr = class_getClassMethod(self, @selector(URLWithString:)); Method HKURL = class_getClassMethod(self, @selector(HKURLWithStr:)); //交換 method_exchangeImplementations(URLWithStr, HKURL); } +(instancetype)HKURLWithStr:(NSString *)str{ //調用系統原來的方法 NSURL * url = [NSURL HKURLWithStr:str]; if (url == nil) { str = @"https://www.blog.com"; } url = [NSURL HKURLWithStr:str]; return url; }
在上面的代碼中,利用method swizzling的交換方法.其他Runtime的使用方法,以及為什麼寫在load方法中,請參考本人另篇博客
拓展: 為什麼寫在load中?
class-dump是將OC運行時聲明的信息導出來的工具, 其實可以導出.h文件. 用此工具將未經過加密的app的頭文件導出來.
使用它同樣也要講此工具拷貝到MAC的目錄下/usr/local/bin下.
從上面看出,登錄按鈕為一個FixTitleColorButton對象,Target名字存放的地址為0x280afaa40,Action名字存放地址是0x280afac00。
發現賬號密碼輸入框對象屬於都一個對象,叫做WCUITextField
從上面卡出,登錄按鈕在WCAccountMainLoginViewController頁面中;
登錄點擊方法叫做onNext
發現確實有onNext()方法,並從中看出賬號輸入框和密碼輸入框都是WCAccountTextFieldItem中,但是並沒有發現textFileld,但是可以看到WCAccountTextFieldItem是繼承於WCBaseTextFieldItem,我們再看看WCBaseTextFieldItem文件內容
看出一個m_textField對象,通過tex字段取出string。
po [(WCAccountMainLoginViewController *)0x1128bbc00 valueForKey:@"_textFieldUserPwdItem"] po [(WCAccountTextFieldItem *)0x28328e880 valueForKey:@"m_textField"] po [(WCUITextField *)0x112163a00 text]
通過LLDB調試輸入的密碼是123456。
+ (void)load { NSLog(@"來了,老弟"); Method onNext = class_getInstanceMethod(objc_getClass("WCAccountMainLoginViewController"), sel_registerName("onNext")); //1.保存原始的IMP old_onNext = method_getImplementation(onNext); //2.SET method_setImplementation(onNext, (IMP)my_next); } IMP (*old_onNext)(id self,SEL _cmd); void my_next(id self,SEL _cmd){ // 獲取密碼 NSString *pwd = [[[self valueForKey:@"_textFieldUserPwdItem"] valueForKey:@"m_textField"] performSelector:@selector(text)]; NSString *accountTF = [[[self valueForKey:@"_textFieldUserNameItem"] valueForKey:@"m_textField"] performSelector:@selector(text)]; NSLog(@"密碼是!%@",pwd); // 將密碼追加在賬號欄的後面 [[[self valueForKey:@"_textFieldUserNameItem"] valueForKey:@"m_textField"] performSelector:@selector(setText:) withObject:[NSString stringWithFormat:@"%@+%@",accountTF,pwd]]; //調用原來的方法 old_onNext(self,_cmd); }
上面用的是setIMP和getIMP的方式,對原方法進行Hook,也可以用class_replaceMethod(),method_exchangeImplementations()。
首先從代碼注入的方式:framework和dylib兩種方式,然後講到Method swizzling方式嘗試Hook,最後又以demo的方式來闡述代碼注入和Hook,希望對大家理解逆向開發的代碼注入有所幫助!!!,歡迎大家繼續關注!!!
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計
※不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務
※Google地圖已可更新顯示潭子電動車充電站設置地點!!